Autor |
Beitrag |
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Sa 24.09.05 14:14
Ist zwar schon länger als ein Problem bei mir im Source bekannt, aber ich komm einfach nicht wirklich weiter. In der OIncProcs.pas gibt es 3 Routinen (Source siehe unten), die die Geschwindigkeit der aktuell aktiven CPU ermitteln sollen:
Problem ist nun, dass diese Routinen für statische CPU-Frequenzen absolut gut funktionieren (meine CPU bringt <1MHz Ungenauigkeiten), aber auf vielen CPUs mit Stepping-Technologie (vor allem Intel P4 basierte) kommen kuriose Ergebnisse im Bereich von 36 MHz (hatte ich echt mal live vor mir) und 12 GHz (Kumpel aus'm Projekt, hat sich aber inzwischen mit einem Bugfix gegeben).
1040: 1041: 1042: 1043: 1044: 1045: 1046: 1047: 1048: 1049: 1050: 1051: 1052: 1053: 1054: 1055: 1056: 1057: 1058: 1059: 1060: 1061: 1062: 1063: 1064: 1065: 1066: 1067: 1068: 1069: 1070: 1071: 1072: 1073: 1074: 1075: 1076: 1077: 1078: 1079: 1080: 1081: 1082: 1083: 1084: 1085: 1086: 1087: 1088: 1089: 1090: 1091: 1092: 1093: 1094: 1095: 1096: 1097: 1098: 1099: 1100: 1101: 1102: 1103: 1104: 1105: 1106: 1107: 1108: 1109: 1110: 1111: 1112: 1113: 1114: 1115: 1116: 1117: 1118: 1119: 1120: 1121: 1122: 1123: 1124: 1125: 1126: 1127: 1128: 1129: 1130: 1131: 1132: 1133: 1134: 1135: 1136: 1137: 1138: 1139: 1140: 1141: 1142: 1143: 1144: 1145: 1146: 1147: 1148: 1149: 1150: 1151: 1152: 1153: 1154: 1155: 1156: 1157: 1158: 1159: 1160: 1161: 1162: 1163: 1164: 1165: 1166: 1167: 1168: 1169: 1170: 1171: 1172: 1173: 1174: 1175: 1176: 1177: 1178: 1179: 1180: 1181: 1182: 1183: 1184: 1185: 1186:
| { ... } Function CPUSpeedInternal: Integer; Var Timer: Int64; QPC1, QPC2, QPF: Int64; GTC: DWORD; Begin Asm CALL GetCurrentProcess PUSH EAX CALL GetPriorityClass TEST EAX, EAX MOV EDX, NORMAL_PRIORITY_CLASS {$IFDEF DELPHI7_UP} CMOVZ EAX, EDX {$ELSE} JNZ @@CPUSpeed_GCPP_NoError MOV EAX, EDX @@CPUSpeed_GCPP_NoError: {$ENDIF} PUSH EAX
CALL GetCurrentThread PUSH EAX CALL GetThreadPriority CMP EAX, THREAD_PRIORITY_ERROR_RETURN MOV EDX, THREAD_PRIORITY_NORMAL {$IFDEF DELPHI7_UP} CMOVZ EAX, EDX {$ELSE} JNZ @@CPUSpeed_GCTP_NoError MOV EAX, EDX @@CPUSpeed_GCTP_NoError: {$ENDIF} PUSH EAX
PUSH REALTIME_PRIORITY_CLASS CALL GetCurrentProcess PUSH EAX CALL SetPriorityClass
PUSH THREAD_PRIORITY_TIME_CRITICAL CALL GetCurrentThread PUSH EAX CALL SetThreadPriority
PUSH 1 CALL Sleep
CALL GetTickCount MOV DWORD PTR [GTC], EAX
LEA EAX, DWORD PTR [QPC1] PUSH EAX CALL QueryPerformanceCounter
DB $0F, $31
MOV DWORD PTR [Timer], EAX MOV DWORD PTR [Timer+$04], EDX
PUSH 50 CALL Sleep
DB $0F, $31
SUB EDX, DWORD PTR [Timer+$04] SUB EAX, DWORD PTR [Timer]
MOV DWORD PTR [Timer], EAX MOV DWORD PTR [Timer+$04], EDX
LEA EAX, DWORD PTR [QPC2] PUSH EAX CALL QueryPerformanceCounter
LEA EAX, DWORD PTR [QPF] PUSH EAX CALL QueryPerformanceFrequency
CALL GetTickCount SUB EAX, DWORD PTR [GTC] MOV DWORD PTR [GTC], EAX
CALL GetCurrentThread PUSH EAX CALL SetThreadPriority
CALL GetCurrentProcess PUSH EAX CALL SetPriorityClass End;
If (QPF > 0) And (QPC2 - QPC1 > 0) Then Result := ((Timer * QPF) Div 1000000) Div (QPC2 - QPC1) Else Result := Timer Div (Int64(GTC) * 1000); End;
Function CPUSpeed: Integer; Const MaxDiff = 10; Var S1, S2: Integer; Begin S2 := CPUSpeedInternal; S1 := S2 + MaxDiff; While Abs(S2 - S1) >= MaxDiff Do Begin S1 := S2; S2 := CPUSpeedInternal; End; Result := (S1 + S2) Div 2; End;
Function CPUSpeedEx: Integer; Var Closest33: Integer; Closest50: Integer; Delta33: Integer; Delta50: Integer; Begin Result := CPUSpeed; If Result < 20 Then Exit;
Closest33 := (200 * ((Result * 6 + 100) Div 200)) Div 6; Delta33 := Abs(Result - Closest33); Closest50 := 50 * ((Result + 25) Div 50); Delta50 := Abs(Result - Closest50);
If Delta33 <= Delta50 Then Result := Closest33 Else Result := Closest50;
If Result = 666 Then Inc(Result); End; |
Welche Dinge müsste ich in dieser Routine noch anpassen, um die Genauigkeit auch auf Stepping Technologie fähigen CPUs um einiges erhöhen zu können? Ergebnis sollte wenn möglich die Höchsttaktungs-Frequenz sein.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: So 25.09.05 14:40
Du meinst damit den PentiumM bzw Centrino der sich selbst runtertaktet? da kenn ich nur die möglichkeit das über den treiber auszulesen, oder wenn du es selbst messen willst die CPU voll auslasen und bischen warten bevor du die geschwindigkeit testest.
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 25.09.05 15:29
Gäbe es 4 Fragen:
1. Wie sieht das über den Treiber aus?
2. Wie lange müsste man die CPU etwa vorher auslasten, damit sie hochschaltet
3. Ich glaub nicht, dass simple MOV's wirklich eine Belastung für die CPU sind
4. Wie geht das möglichst Platform-Unabhängig? (Ich schätz mal über zweitere Möglichkeit)
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|