1

J'ai l'impression d'être le seul à me poser cette question triso :
Comment récupérer la fréquence d'un CPU sous LINUX, sans aller la pêcher dans /proc/cpuinfo ?
Je souhaite convertir le TSC en secondes.

Les techniques que mon copain google m'a indiqué sont soit :
- le TSC d'un sleep de 1 seconde, et d'en déduire la fréquence - pas envisageable car le code mettrait systématiquement 1s de plus à tourner. Et en plus ce n'est pas très précis.
- utiliser sysctlbyname, mais ce n'est valable que pour BSD car une variable du kernel contient la fréquence du CPU... et je suis sous LINUX

Au pire je ferais un appel système à coup de grep et de awk, mais ce n'est pas efficace, précis, élégant.

Quelqu'un à une idée ? gni
Merci
Gare à celui qui touche a mes chips quand je code !

2

on peut savoir pourquoi proc ne te convient pas?

3

En fait, c'est comme les benchmarks... Si tu te renseignes sur les benchmarks CPU sous linux, on te filera un lien vers /proc/cpuinfo qui affiche généralement la fréquence "de référence" du CPU et pas la fréquence actuelle... Quant au test de performance, tu peux oublier...
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

4

sinon, t'as le package cpufrequtils qui permet de tuner la fréquence ET de lire la fréquence actuelle...
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

5

squalyl > comme l'as dit Vince, la fréquence du CPU dépend des paramètres d'économie d'énergie définis dansl e BIOS.

vince > je ne maitrise pas l'installation de packages sur le Linux où tourne le code. Et installer un package pour connaitre la fréquence du CPU me laisse un peu perplexe... et l'idée d'inclure le code de CPUFREQUTILS dans mon code ça sent la galère.
Gare à celui qui touche a mes chips quand je code !

6

en fait il s'appuie sur le module CPUID, s'il est présent sur ta machine, tu peux probablement l'interroger directement
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

7

Az : c'est des procs x86, ou ça doit être portable ?

Dans le premier cas, j'avais fait un bout de code pour faire ça il y a longtemps, faut que je regarde.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

8

4: j'avais pas pensé à ça.

sinon le code de la lib en question doit être recompilable en statique dans $home, puis intégrable à ton code.

9

c'est des x86 :-p (sans commentaires, merci)
Gare à celui qui touche a mes chips quand je code !

10

OK, je vais regarder.

Le principe de base : lire périodiquement le TSC et un autre timer de fréquence connue, et en déduire la fréquence du proc. Sous Windows j'avais utilisé QueryPerformanceCounter(), qui s'appuie dans le pire des cas sur le PIT (sa fréquence est ~ 1,2 MHz). On doit pouvoir faire pareil sous Linux.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

11

C'est un peu la technique dont je parlais plus haut, il y a gettimeoftheday par exemple, mais ça impose qu'il n'y ait pas trop de latence entre les appels des deux compteurs si on veut avoir des temps pas trop faux.
Gare à celui qui touche a mes chips quand je code !

12

Exact, mais ça, de toute façon, c'est un problème fondamental. Le seul moyen de l'éviter serait de désactiver les interruptions temporairement, pour que l'ensemble lecture TSC+lecture autre compteur soit atomique. Vu que ça va fondamentalement à l'encontre du principe d'un OS préemptif, je sais même pas si c'est possible en user-mode, et même si c'était le cas il faudrait que le processus soit SUID root.

Cependant je pense que si tu fais faire ça par un thread dédié, auquel tu donnes une priorité élevée, les résultats devraient être relativement précis.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

13

si y'a une latence d'appel, tu peux la négliger si tu mesures assez longtemps, et l'éliminer en faisant 2 mesures et en trouvant l'offset (y=ax+b) a donne la vitesse en instructions par seconde et b le temps de latence constant à ajouter aux mesures.

pour virer l'influence des irq on peut moyenner plusieurs mesures.

Je pense qu'il n'y a que le kernel qui peut désactiver les irq, et que de toute façon ce n'est pas nécessaire:

le performance counter compte un nb de cycles, irq ou pas (enfin je pense, non?)
la rtc donne le vrai temps écoulé.

14

Si, c'est nécessaire. Le problème n'est pas le fait que les compteurs ne soient pas lus simultanément (si tu supposes que le temps d'exécution est constant, ça s'annule quand tu calcules la différence, et de toute façon c'est complètement négligeable par rapport à la durée mesurée), mais le risque qu'il y ait un context-switch entre la lecture des deux compteurs. Dans ce cas ta mesure va être faussée (plus ou moins, suivant le temps passé à exécuter un autre processus).

Tu peux moyenner, mais ça pose 2 problèmes :
- l'erreur n'est pas centrée sur zéro (la durée ne peut être que rallongée, pas diminuée)
- vu que la fréquence du processeur n'est pas fixe, moyenner revient à effectuer un filtre passe-bas, donc à détruire de l'information
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

15

vince (./3) :
Si tu te renseignes sur les benchmarks CPU sous linux, on te filera un lien vers /proc/cpuinfo qui affiche généralement la fréquence "de référence" du CPU et pas la fréquence actuelle...


[code]spectras@217917lpweb001:~$ grep </proc/cpuinfo MHz
cpu MHz : 1599.971
spectras@217917lpweb001:~$ sudo echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
spectras@217917lpweb001:~$ grep </proc/cpuinfo MHz
cpu MHz : 2400.006
spectras@217917lpweb001:~$[/code]

16

17

(jusqu'à l'installation de cpuid, je n'avais que la fréquence de référence, il faut donc des modules en plus, et azrael a l'air de dire qu'il ne peut rien installer)
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

18

Ma contrainte est que je suis en mode utilisateur, sans aucun privilège. L'acquisition de la fréquence se fait avec un code séquentiel (1 seul thread).

Dans mon cas, le code a un phase d'initialisation des données. L'idée serait en effet de faire une mesure durant cette phase d'initialisation. Si je peux éviter les solutions exotiques grin

vince > j'ai rapidement cherché comment intérroger CPUID, je n'ai pas trouvé de solution pour l'instant. Ca doit être néanmoins possible.

squalyl > le TSC donne le vrai temps écoulé (wall clock). Il doit y avoir un autre compteur qui donne les cycles CPU, mais je n'en connais pas le nom.

EDIT :
je vais faire le cochon et faire un appel système en faisant un grep pipé sur un awk pour récupérer la fréquence... quand à savoir à quel point c'est précis...
Gare à celui qui touche a mes chips quand je code !

19

Tu es sûr que tu ne confonds pas ? Le TSC est un "simple" compteur de cycles d'horloge 64 bits, ça ne mesure pas le temps écoulé. Je te renvoie à la doc Intel sur l'instruction RDTSC smile
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

20

Zerosquare (./19) :
Tu es sûr que tu ne confonds pas ? Le TSC est un "simple" compteur de cycles d'horloge 64 bits, ça ne mesure pas le temps écoulé. Je te renvoie à la doc Intel sur l'instruction RDTSC smile

d'après la doc (http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html) :
"Constant TSC behavior ensures that the duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if the processor core changes frequency. This is the architectural behavior moving forward."

Mais pour ce que j'ai l'habitude des docs hardware... 4000 pages quand même.
Gare à celui qui touche a mes chips quand je code !

21

hum

Bon, faut que je regarde... les docs que j'avais n'indiquaient pas ça, et quand j'avais fait des tests sur un proco avec réglage dynamique de la fréquence (un portable), ça suivait bien les variations de la fréquence d'horloge du processeur. Mais c'était vers 2003, donc ils peuvent avoir changé le principe depuis.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

22

Zerosquare >
J'ai toujours connu ça:
-avant 2000: CPU à fréquence constante
-après 2008 (pour moi, pour le TSC je n'en sais rien): incrément variable pour le TSC.
Gare à celui qui touche a mes chips quand je code !

23

vince (./17) :
(jusqu'à l'installation de cpuid, je n'avais que la fréquence de référence, il faut donc des modules en plus, et azrael a l'air de dire qu'il ne peut rien installer)
Le /proc est une interface du noyau, il n'y a rien à ajouter.
Tu peux suivre les appels à partir de ici : http://lxr.linux.no/#linux+v3.3/arch/x86/kernel/cpu/proc.c#L89
Pour résumer comment la valeur est récupérée :
=> s'il y a un driver cpufreq activé, c'est lui qui renvoie la valeur
=> sinon, la valeur calculée lors de la calibration du boot est renvoyée. Elle est calculée avec le TSC justement.
(=> s'il n'y a pas de TSC sur le cpu, la ligne ne s'affiche pas du tout)

24

je dis juste ce que j'ai vu : un cpu qui gère inteligent step (j'ai pas le nom exact, le truc d'intel de gestion de la freq) renvoyait toujours la valeur "usine" je suis ptet tombé sur une config atypique ou sur un noyeau non compatible, je ne sais pas...
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

25

Peut-être simplement qu'il ne changeait pas sa vitesse dynamiquement avant que tu n'installes ces softs ?
Sur la plupart des distribs, cette fonctionnalité n'est pas utilisée par défaut car elle dégrade la réactivité perçue par l'utilisateur.

Sur Ubuntu (10 je crois), sur mon laptop, par défaut il est en powersave sur batterie, et en performance sur secteur, et le scaling dynamique (ondemand governor) n'est même pas disponible.

26

peut-être...
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

27

utilise l'instruction RTDSC pour lire le TSC (ou l'intrinsic __rtdsc(), peu importe)
t'as pas besoin de bencher 1 s... si tu utilise un timer qui a une granularite pas trop pourrie, juste 5 ou 10 ms c'est largement suffisant.

sinon, t'appelle l'instruction CPUID et tu recupere la string de description CPU.
c'est tres probablement pas standard du tout, mais tu peux eventuellement parser cette string pour essayer de voir si il y a la frequence dedans.
(et eventuellement fallbacker sur la mesure de qques millisecondes avec __rtdsc() si tu trouve pas.

par exemple, sur mon CPU, la string processeur, c'est ca:

"Intel(R) Core(TM)2 Quad CPU Q9450 @ 2.66GHz"

retournee par l'instruction "cpuid" dans 3 des 4 registres de retour: ebx, ecx et edx, lorsque tu l'appelle avec eax et ecx a 0

avatar
HURRRR !

28

tiens, tant qu'a faire:

perso j'utilise ce petit helper pour wrapper cpuid:
struct SCPUIDReport { hh_u32 EAX; hh_u32 EBX; hh_u32 ECX; hh_u32 EDX; SCPUIDReport() : EAX(0), EBX(0), ECX(0), EDX(0) {} void Capture(hh_u32 leaf, hh_u32 subLeaf = 0); };
extern "C" { hh_u32 cpuid_is_available(); } void SCPUIDReport::Capture(hh_u32 leaf, hh_u32 subLeaf) { cpuid_get_info(this, leaf, subLeaf); }

et ca dans un .asm separe:

.intel_syntax noprefix
		.text
		.global		cpuid_get_info

cpuid_get_info:
		push	edi
		push	ebx
		mov		edi, DWORD PTR  4[esp + 8]	# addr of start of output array
		mov		eax, DWORD PTR  8[esp + 8]	# leaf
		mov		ecx, DWORD PTR 12[esp + 8]	# subleaf
		cpuid
		mov		DWORD PTR [edi +  0], eax
		mov		DWORD PTR [edi +  4], ebx
		mov		DWORD PTR [edi +  8], ecx
		mov		DWORD PTR [edi + 12], edx
		pop		ebx
		pop		edi
		ret



'hh_u32' est typedef a uint32_t sur GCC, unsigned __int32 sur msvc
avatar
HURRRR !

29

(tu peux ptet remplacer source=asm par un simple pre)
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

30

smile
avatar
HURRRR !