begin process at 2010 02 10 04:04:59
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Système

 > RÉCUPÉRER LA FRÉQUENCE DU PROCESSEUR

RÉCUPÉRER LA FRÉQUENCE DU PROCESSEUR


 Information sur la source

Note :
10 / 10 - par 2 personnes
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Système Source .NET ( DotNet ) Classé sous :frequence, processeur, cpu, asm, assembleur Niveau :Initié Date de création :09/06/2004 Date de mise à jour :10/12/2007 20:09:37 Vu / téléchargé :17 656 / 614

Auteur : Xya

Ecrire un message privé
Commentaire sur cette source (18)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Cette source classique permet de récupérer une valeur approchée de la fréquence de son processeur. Comme je n'en ai pas vu pour C#/.NET, je l'ai adapté en C#. Cette implémentation alloue de la mémoire non managée pour y écrire un bout de code en assembleur, puis l'exécute en créant un thread dont le point d'entrée est l'adresse de la mémoire contenant le code asm.

Source

  • public struct CpuFreqParams
  • {
  • //addresse de QueryPerformanceCounter
  • public IntPtr lpQPCounterAddress;
  • //temps à attendre pendant le test
  • public long testSpan;
  • //nombre de cycles passés pendant le test
  • public long nCycles;
  • }
  • //code asm utilisé. un peu plus long que la plupart de codes de ce genre
  • //à cause de l'addition/soustraction d'entiers 64 bits (avec add/adc et sub/sbb)
  • //et de la structure utilisée pour les paramètres, pour être lancé comme thread
  • __declspec(naked) void __stdcall GetCPUFrequency( LPVOID lpParams )
  • {
  • //Pile locale:
  • //
  • //UINT64 endCycle (ebp-68 et ebp-64)
  • //UINT64 startCycle (ebp-60 et ebp-56)
  • //UINT64 tickCurrent (ebp-52 et ebp-48)
  • //UINT64 tickEnd (ebp-44 et ebp-40)
  • //UINT64 tickStart (ebp-36 et ebp-32)
  • //DWORD lpQPCounterAddress (ebp-28)
  • //UINT64 testSpan (ebp-20 et ebp-16)
  • //UINT64 nCycles (ebp-12 et ebp-8)
  • __asm
  • {
  • push ebp
  • mov ebp, esp
  • ;alloue la pile locale
  • sub esp, 64
  • ;sauvegarde les registres et les flags
  • push eax
  • push ecx
  • push edx
  • push esi
  • push edi
  • pushfd
  • ;vérifie que lpParams n'est pas null
  • cmp dword ptr [ebp+8], 0
  • je clear
  • ;copie les paramètres dans la pile
  • mov esi, dword ptr [ebp+8]
  • lea edi, dword ptr [ebp-28]
  • mov ecx, 24
  • cld
  • rep movsb
  • ;vérifie que lpQPCounterAddress n'est pas null
  • cmp dword ptr [ebp-28], 0
  • je clear
  • ;obtient le nombre de ticks avec QueryPerfCounter
  • lea ecx, dword ptr [ebp-36]
  • push ecx
  • call dword ptr [ebp-28]
  • ;ajoute testSpan au nombre ticks pour avoir l'"heure" en ticks à attendre
  • mov ecx, dword ptr [ebp-36]
  • add ecx, dword ptr [ebp-20]
  • mov dword ptr [ebp-44], ecx
  • mov ecx, dword ptr [ebp-32]
  • adc ecx, dword ptr [ebp-16]
  • mov dword ptr [ebp-40], ecx
  • ;obtient le nombre de cycles du processeur
  • rdtsc
  • mov dword ptr [ebp-60], eax
  • mov dword ptr [ebp-56], edx
  • ;boucle d'attente
  • L1:
  • ;obtient le nombre de ticks avec QueryPerfCounter
  • lea ecx, dword ptr [ebp-52]
  • push ecx
  • call dword ptr [ebp-28]
  • ;regarde si on doit sortir de la boucle
  • lea esi, dword ptr [ebp-44]
  • lea edi, dword ptr [ebp-52]
  • mov ecx, 2
  • cld
  • rep cmpsd
  • jae L1
  • ;obtient le nombre final de cycles du processeur
  • rdtsc
  • mov dword ptr [ebp-68], eax
  • mov dword ptr [ebp-64], edx
  • ;obtient le nombre de cycles passés pendant le test
  • mov ecx, dword ptr [ebp-68]
  • sub ecx, dword ptr [ebp-60]
  • mov dword ptr [ebp-12], ecx
  • mov ecx, dword ptr [ebp-64]
  • sbb ecx, dword ptr [ebp-56]
  • mov dword ptr [ebp-8], ecx
  • ;copie la pile vers les paramètres
  • lea esi, dword ptr [ebp-28]
  • mov edi, dword ptr [ebp+8]
  • mov ecx, 24
  • cld
  • rep movsb
  • clear:
  • popfd
  • pop edi
  • pop esi
  • pop edx
  • pop ecx
  • pop eax
  • add esp, 64
  • mov esp, ebp
  • pop ebp
  • ret
  • }
  • }
public struct CpuFreqParams
{
	//addresse de QueryPerformanceCounter
	public IntPtr lpQPCounterAddress;
	//temps à attendre pendant le test
	public long testSpan;
	//nombre de cycles passés pendant le test
	public long nCycles;
}

//code asm utilisé. un peu plus long que la plupart de codes de ce genre
//à cause de l'addition/soustraction d'entiers 64 bits (avec add/adc et sub/sbb)
//et de la structure utilisée pour les paramètres, pour être lancé comme thread
__declspec(naked) void __stdcall GetCPUFrequency( LPVOID lpParams )
{
	//Pile locale:
	//
	//UINT64 endCycle			(ebp-68 et ebp-64)
	//UINT64 startCycle			(ebp-60 et ebp-56)
	//UINT64 tickCurrent			(ebp-52 et ebp-48)
	//UINT64 tickEnd			(ebp-44 et ebp-40)
	//UINT64 tickStart			(ebp-36 et ebp-32)
	//DWORD lpQPCounterAddress		(ebp-28)
	//UINT64 testSpan			(ebp-20 et ebp-16)
	//UINT64 nCycles			(ebp-12 et ebp-8)
	__asm
	{
		push ebp
		mov ebp, esp
		;alloue la pile locale
		sub esp, 64
		;sauvegarde les registres et les flags
		push eax
		push ecx
		push edx
		push esi
		push edi
		pushfd
		;vérifie que lpParams n'est pas null
		cmp dword ptr [ebp+8], 0
		je clear
		;copie les paramètres dans la pile
		mov esi, dword ptr [ebp+8]
		lea edi, dword ptr [ebp-28]
		mov ecx, 24
		cld
		rep movsb
		;vérifie que lpQPCounterAddress n'est pas null
		cmp dword ptr [ebp-28], 0
		je clear
		;obtient le nombre de ticks avec QueryPerfCounter
		lea ecx, dword ptr [ebp-36]
		push ecx
		call dword ptr [ebp-28]
		;ajoute testSpan au nombre ticks pour avoir l'"heure" en ticks à attendre
		mov ecx, dword ptr [ebp-36]
		add ecx, dword ptr [ebp-20]
		mov dword ptr [ebp-44], ecx
		mov ecx, dword ptr [ebp-32]
		adc ecx, dword ptr [ebp-16]
		mov dword ptr [ebp-40], ecx
		;obtient le nombre de cycles du processeur
		rdtsc
		mov dword ptr [ebp-60], eax
		mov dword ptr [ebp-56], edx
		;boucle d'attente
L1:
		;obtient le nombre de ticks avec QueryPerfCounter
		lea ecx, dword ptr [ebp-52]
		push ecx
		call dword ptr [ebp-28]
		;regarde si on doit sortir de la boucle
		lea esi, dword ptr [ebp-44]
		lea edi, dword ptr [ebp-52]
		mov ecx, 2
		cld
		rep cmpsd
		jae L1
		;obtient le nombre final de cycles du processeur
		rdtsc 
		mov dword ptr [ebp-68], eax
		mov dword ptr [ebp-64], edx
		;obtient le nombre de cycles passés pendant le test
		mov ecx, dword ptr [ebp-68]
		sub ecx, dword ptr [ebp-60]
		mov dword ptr [ebp-12], ecx
		mov ecx, dword ptr [ebp-64]
		sbb ecx, dword ptr [ebp-56]
		mov dword ptr [ebp-8], ecx
		;copie la pile vers les paramètres
		lea esi, dword ptr [ebp-28]
		mov edi, dword ptr [ebp+8]
		mov ecx, 24
		cld
		rep movsb
clear:
		popfd
		pop edi
		pop esi
		pop edx
		pop ecx
		pop eax
		add esp, 64
		mov esp, ebp
		pop ebp
		ret
	}
}

 Conclusion

Ce code devrait marcher pour tous les processeurs à partir du Pentium, et sur toutes les versions de Windows à partir de 2000 (à cause de l'appel à VirtualProtect). Le test effectué est sur un AMD 2400+ (2.0 Ghz) sous Windows XP. Pour les systèmes multiprocesseurs/multicore/HyperThreading, le test peut échouer s'il est trop long (ex: 1 sec), une durée de 10 ms ou moins devrait réussir dans la plupart des cas.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

10 décembre 2007 20:06:11 :
- Correction d'un bug de protection de mémoire avec Vista et les éditions 64 bit de Windows - Encapsulation du code nécessaire pour exécuter du code assembleur dans une classe (RunAsm), utilisée par la classe CpuFrequency
10 décembre 2007 20:09:37 :
Corrigé un bug de protection de mémoire qui causait une erreur avec Vista et les versions 64 bit de Windows. Encapsulé le code nécessaire pour exécuter du code assembleur dans une classe (RunAsm), qui peut être utilisée indépendamment de la classe CpuFrequency, mais qui est utilisée par celle-ci.

 Sources du même auteur

Source .NET (Dotnet) OBTENIR LE NOM DETAILLE DU SYSTEME D'EXPLOITATION
Source avec Zip Source avec une capture Source .NET (Dotnet) GÉNÉRATEUR DE SOLUTIONS VISUAL STUDIO .NET

 Sources de la même categorie

Source avec Zip Source avec une capture Source .NET (Dotnet) GESTION DES LANGUES, COUNTRIES, CHAÎNES DE CARACTÈRE SIMPLE par gourky
Source avec Zip Source avec une capture Source .NET (Dotnet) EXPLORER LA MFT D'UNE PARTITION NTFS par Willi
Source avec Zip Source avec une capture Source .NET (Dotnet) WRAPPER COMPLET SUR L'API DE BIOMÉTRIE DE WINDOWS 7 par Willi
Source avec Zip Source .NET (Dotnet) UTILISER L'ASSISTANT DE GRAVURE DE WINDOWS par Willi
Source avec Zip Source avec une capture Source .NET (Dotnet) EASYDESKXP par neo2k2

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture Source .NET (Dotnet) UTILISATION DES PERFORMANCECOUNTER par jdek
Source avec Zip Source avec une capture Source .NET (Dotnet) [.NET2] MONITEUR GRAPHIQUE CPU ET RAM par Willi
Source .NET (Dotnet) FONCTION D'AFFICHAGE DU NOM DU PROCESSEUR AVEC WMI par JuLsupinfo

Commentaires et avis

Commentaire de coq le 10/06/2004 09:42:30 administrateur CS

Et hop en favoris, l'idée de la mesure me plait bien, merci

Il semble juste qu'il y ai un petit probleme avec les procs HyperThreading (et potentiellement multiproc donc), dans mon cas il donne souvent la valeur 0,001 sur le test de 1s (l'utilisation du test 1ms semble resoudre le probleme)

Comme solution alternative on peut utiliser le WMI et sa classe Win32_Processor (espace root/cimv2)
propriétés CurrentClockSpeed/MaxClockSpeed (unité = Mhz)

Commentaire de Xya le 10/06/2004 14:49:53

Voilà, j'ai modifié mon code pour pouvoir spécifier l'ID du processeur sur un système multiprocesseur, mais comme je n'ai pas de processeur HyperThreading sous la main je n'ai pas pu faire de tests.


Xya

Commentaire de coq le 10/06/2004 16:28:24 administrateur CS

le code marche niquel
on a toujours des 0.001 mais bon ça doit etre normal
faudrais que je me documente un peu pour savoir comment fonctionne ce fameux ht

Commentaire de BruNews le 20/06/2004 12:27:44 administrateur CS

Xya > regarde si tu peux retranscrire l'ASM de:
http://www.cppfrance.com/code.aspx?ID=23837
va bon pour tous processeurs, teste jusqu'au bixeon 3.06 impec.

Commentaire de Xya le 20/06/2004 15:11:43

Quand tu dis retranscrire, tu veux bien dire convertir le code ASM en:

private static byte[] GetCpuFrequencyCode()
{
byte[] code = new byte[147];
//push ebp
code[  0] = 0x55;
//mov ebp, esp
code[  1] = 0x8B; code[  2] = 0xEC;
//;alloue la pile locale
//sub esp, 64
        ...

Commentaire de BruNews le 20/06/2004 15:19:39 administrateur CS

'retranscrire' n'est surement pas le bon terme, juste voir comment tu peux t'en servir dans ton C#, moi aucune idee.
Au fait, pourquoi tu fais une stackframe:
push ebp
mov ebp, esp
c'est utile ici ?

Commentaire de Xya le 20/06/2004 15:43:53

Pour ton code je vais pas pouvoir l'utiliser directement puisqu'il se lie statiquement aux QueryPerfX, ce qui n'est pas possible avec un assembly .NET. (C'est pour ca que dans mon code l'appellant utilise LoadLibrary/GetProcAddress et passe comme paramètre l'adresse de QueryPerformanceCounter)

Sinon je pense que la stackframe est utile si tu regardes tout l'espace que le code alloue sur la stack:

    //Pile locale:
    //
    //UINT64 endCycle           (ebp-68 et ebp-64)
    //UINT64 startCycle         (ebp-60 et ebp-56)
    //UINT64 tickCurrent            (ebp-52 et ebp-48)
    //UINT64 tickEnd            (ebp-44 et ebp-40)
    //UINT64 tickStart          (ebp-36 et ebp-32)
    //DWORD lpQPCounterAddress      (ebp-28)
    //UINT64 testSpan           (ebp-20 et ebp-16)
    //UINT64 nCycles            (ebp-12 et ebp-8)

Commentaire de BruNews le 20/06/2004 15:53:32 administrateur CS

Le mien ne prenant que 28 octets sur la pile pour un tres court instant, devrait plus etre necessaire stackframe, enfin c'est toi qui voit.
Je m'en retourne au code natif, vraiment trop le bord... a mon gout ces codes interpretes.
Bossez bien.

Commentaire de coq le 20/06/2004 16:00:07 administrateur CS

Si tu veux te servir du code de BruNews tu le compile sous forme d'une dll qui exporte les methodes et tu t'en sert via les DllImport non ?

Commentaire de BruNews le 20/06/2004 16:02:41 administrateur CS

ça je peux vous le faire en 2 minutes, suffit de demander.

Commentaire de Xya le 20/06/2004 18:50:53

L'idée c'est que ca marche sans DLL, juste en ajoutant un fichier source au projet. Sinon, j'aurai pu faire une dll avec mon code asm et la charger avec DllImport.
Sinon pour le stackframe l'ASM est en encore nouveau pour moi alors que le stackframe soit nécessaire ou pas je sais pas trop.

Commentaire de georgeduke le 07/08/2005 11:05:14

Ton source est vraiment sympa car il n'y a pas beaucoup d'exemples (en français) de l'implémentation d'asm dans C# !! (au fait je t'ai envoyé un message privé à ce propos)

Commentaire de piradom le 10/12/2007 15:10:17

Salut,

lorsque je lance l'execution de ce code sous "Visual Studio 2008", l'application bug en tentant d'obtenir la frequence du CPU;

Si quelqu'un a une idée sa serait sympa, Merci!

Commentaire de Xya le 10/12/2007 19:46:15

Salut,

Quelle version et édition de Windows utilises tu? (XP/Vista, 32/64 bit)
Si c'est Vista ou XP 64, l'erreur doit venir du fait que la mémoire allouée par AllocHGlobal ne possède pas le droit d'exécution.

Pour corriger cela, il fait ajouter un appel à VirtualProtect avant l'appel à CreateThread:

//ajoute le droit d'exécution à la page de mémoire allouée
int oldProtect;

VirtualProtect( hCode, new IntPtr( code.Length ), PAGE_EXECUTE_READWRITE, out oldProtect );

//crée un thread qui va exécuter la fonction ASM
hThread = CreateThread( IntPtr.Zero,
...

//constante et déclaration de VirtualProtect
private const int PAGE_EXECUTE_READWRITE = 0x40;

[DllImport("Kernel32.dll")]
private static extern void VirtualProtect( IntPtr adress, IntPtr size, int newProtect, out int oldProtect );

Commentaire de Xya le 10/12/2007 19:51:45

Enfait je viens de me rendre compte que j'avais mis à jour mon code sans envoyer la version mise à jour sur ce site, ce que je vais faire de suite.

Commentaire de piradom le 10/12/2007 19:58:30

Ok, donc j'attends que tu fasse la mise a jour

Merci!!!

Commentaire de piradom le 10/12/2007 20:03:53

Au fait je suis sous vista, et je vient d'essayer avec l'ajout du nouveau code,
eh bien sa marche parfaitement:)

Commentaire de Xya le 10/12/2007 20:18:46

Content de l'entendre :)

Sinon désolé pour les mises à jour multiples, et j'ai également oublié de retirer un fichier qui n'a rien à voir (FileDecrypt.cs).

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Frequence de processeur [ par Zakki49 ] Bonjour à tous, j'ai urgemment besoin de votre aide, voila je developpe une petite appli affichant la frequence du processeur en temps réel. Et je ve Mon sous-programme ne répond pas lors de l'appel [ par LilBisk ] Tout est dans le titre :( Le sous-programme en question : [code=cs] /* Il renvoie la valeur de la frequence choisie par une entreprise à partir de l Infos Bios et CPU [ par Lille59 ] Question pour un champion... Comment faire pour récupérer les infos du Bios et du processeur dans une API ???<b instruction c# pour CPU [ par rerereda ] Bonjour,je voudrais savoir s'il existe une instruction spécifique que je pourrais introduire dans mon "main.cs" pour mesurer la charge CPU de mon PC a [C#] pre-processeur & TreeViewCheckBox [ par scoubidou944 ] 1°) Tout développeur C++ se souvient de#ifdef _DEBUG#else#endifMaintenant, sous Visual C# .NET, _DEBUG n'existe plus, C koi alors l'expression pour di Processeur [ par gregomtl ] Salut tout le monde...Comment fait on pour savoir quel % du processeur est utilise par un programme [ex. programme TOTO.exe] ?Merci a tous ! utilisation cpu par processus [ par Adidas2 ] Salut tous le mondeJe cherche à obtenir l'utilisation CPU de chaque processus lancé quelqu'un aurait une idée de la fonction à utiliser svp ?Langage : figer le nom du processeur sous xp [ par rasta76 ] comment faire pour que le nom situ&#233; dans la base de registre processeurnamestringsoit fig&#233; c'est &#224; dire que lorsque l'on rentre un nom Assembleur [ par RM50Man ] Est ce qu 'il est possible d ajouter du code assembleur ds du code c#RM50man Thread et charge CPU [ par JuS ] Voici l'&#233;nonc&#233; de mon probl&#232;me : J'ai un programme client qui communique avec un autre programme serveur. Quand mon client se connecte


Nos sponsors


Sondage...

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,076 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales