[VC++] retrouver la fréquence d'un CPU

retrouver la fréquence d'un CPU [VC++] - Programmation

Marsh Posté le 13-05-2001 à 21:10:39    

J'ai trouvé un bout de code qui me donne (via des instructions en assembleur) le type et la fréquance du cpu de la machine, mais il arrive que la valeur de la fréquence soit fausse (un peu trop élevée ou carrément négative).
 
Vous connaissez un moyen de récupérer ces infos ?


---------------
SetiCommander, le setiseur à la chaîne ...
Reply

Marsh Posté le 13-05-2001 à 21:10:39   

Reply

Marsh Posté le 13-05-2001 à 22:05:06    

Pour obtenir une précision optimale, assure-toi que le bout de code tourne en priorité maximale :
process en REALTIME_PRIORITY_CLASS et thread en THREAD_PRIORITY_TIME_CRITICAL.

Reply

Marsh Posté le 13-05-2001 à 23:30:48    

Arg j'viens de te poster un truc minicooler mais sur Seti :lol:


---------------
VT ... Vaucluse / Vrille(euse :sarcastic: ) c'est pareil tant qu'il y a l'humour :D
Reply

Marsh Posté le 14-05-2001 à 20:24:58    

ouaip j'ai u visu, mais je t'ai répondu ...
 
merci z51, mais c'est pourtant ce que j'ai fait (enfin ce qui est fait dans le bout de code)


---------------
SetiCommander, le setiseur à la chaîne ...
Reply

Marsh Posté le 14-05-2001 à 20:33:01    

Alors ça peut venir de ta méthode de calcul. Tu fais comment ?

Reply

Marsh Posté le 14-05-2001 à 21:18:56    

ben voilà le code que j'utilise
 
int CCPUFeatures::GetCpuSpeed()
{
 int time;  
 int subtime;
 int nPriorityClass;
 int nPriorityThread;
 int nTmp;
 int result;
    nPriorityClass = GetPriorityClass(GetCurrentProcess);
    nPriorityThread = GetThreadPriority(GetCurrentThread);
    SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);
    SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
 __asm  
 {
  cpuid
  rdtsc
  mov subtime, eax
  cpuid
  rdtsc
  sub eax, subtime
  mov subtime, eax
 
  cpuid
  rdtsc
  mov subtime, eax
  cpuid
  rdtsc
  sub eax, subtime
  mov subtime, eax
 
  cpuid
  rdtsc
  mov subtime, eax
  cpuid
  rdtsc
  sub eax, subtime
  mov subtime, eax  
 }
 __asm
 {
  cpuid    
  rdtsc    
  mov time, eax
 }
 Sleep(1500);
 __asm
 { cpuid    
  rdtsc    
  sub eax, time  
  mov time, eax
 }
 
 time = time - subtime;  
 SetThreadPriority(GetCurrentThread, nPriorityThread);
 SetPriorityClass(GetCurrentProcess, nPriorityClass);
 nTmp=time/1500000;
 switch(nTmp%100)
 {
 case 1:
  result=nTmp-1;
  break;
 case 51:
  result=nTmp-1;
  break;
 case 81:
  result=nTmp-1;
  break;
 case 67:
  result=nTmp-1;
  break;
 case 34:
  result=nTmp-1;
  break;
 case 99:
  result=nTmp+1;
  break;
 case 49:
  result=nTmp+1;
  break;
 case 79:
  result=nTmp+1;
  break;
 case 65:
  result=nTmp+1;
  break;
 case 32:
  result=nTmp+1;
  break;
 default:
  result=nTmp;
 }
 return result;  
}
 
à l'origine, c'était un sleep (2000), mais c'étais long et je trouvais que sur mes 2 PC (TBird 800@1050 et pétroi 700) les valeurs étaient correctes. j'ai aussi modifié en concéquence nTmp=time/1500000;


---------------
SetiCommander, le setiseur à la chaîne ...
Reply

Marsh Posté le 14-05-2001 à 21:20:39    

minicooler, va jeter un oeil dans les sources de SetiSpy, y'a des appels assembleurs pour recuperer toutes ces infos...


---------------
www.alliancefrancophone.org ... Home is where the heart is
Reply

Marsh Posté le 14-05-2001 à 22:25:48    

Le problème vient du Sleep qui manque de précision (épargnez-moi les jeux de mots éculés SVP :D )
 
Le mieux est d'utiliser QueryPerformanceFrequency et QueryPerformanceCounter. Le problème de ces fonctions est qu'elles utilisent une base de temps différente selon le CPU et l'OS. Mais l'essentiel est d'avoir deux bases de temps, et pour l'autre on peut prendre le compteur de cycle interne (rdtsc), l'idée étant d'avoir deux deltas, un pour chaque base.
 
Donc :  
 

  • tu te mets en priorité maximale (comme tu l'as fait)


  • tu récupères la fréquence du QPC :

LARGE_INTEGER pf;
QueryPerformanceFrequency(&pf);
 

  • tu prends une mesure des deux compteurs :

LARGE_INTEGER valeur0;
float ticks0;
QueryPerformanceCounter(&valeur0);
__asm{
   rdtsc
   mov ticks0, eax
}
 

  • tu attends qques ms pour obtenir des deltas corrects, en utilisant une boucle de calcul par exemple... sa durée n'importe pas du tout dans la précision du calcul.


  • tu reprends à nouveau une valeur des deux compteurs.

LARGE_INTEGER valeur1;
float ticks1;
QueryPerformanceCounter(&valeur1);
__asm{
   rdtsc
   mov ticks1, eax
}
 

  • et voilà, la fréquence en Hz vaut :

freq = (float)(ticks1-ticks0) * pf.LowPart / (valeur1.LowPart - valeur0.LowPart).
 

  • tu te remets en priorité normale (comme tu l'as fait)


 
Avec un P2 ou un P3 sous NT, QueryPerformanceFrequency renvoie directement la fréquence du cpu, mais le calcul fonctionne quand même, car alors les deux deltas sont égaux.
 
 
oilà oilà ...

 

[edit]--Message édité par z51--[/edit]

Reply

Marsh Posté le 15-05-2001 à 20:40:42    

merci beaucoup z51, ça c'est ce que l'on appelle une réponse précise.
 
JWhy, je n'ai pas Delphi  :cry:  :cry:


---------------
SetiCommander, le setiseur à la chaîne ...
Reply

Marsh Posté le 15-05-2001 à 21:22:03    

y'a pas de quoi ...  :)  
 
Par contre je me suis planté :D  : ticks0 et ticks1 sont des unsigned long, et non pas des float.

Reply

Marsh Posté le 15-05-2001 à 21:22:03   

Reply

Marsh Posté le 16-05-2001 à 20:11:11    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed