2008-09-15 12 views

Respuesta

0

No estoy seguro de por qué necesita el montaje para esto. Si estás en un equipo que tiene el sistema de ficheros/proc, a continuación, ejecutar:

> cat /proc/cpuinfo 

que podría darle lo que necesita.

1

Esa era la intención de cosas como BogoMIPS, pero las CPU son mucho más complicadas hoy en día. Las CPU superescalares pueden emitir múltiples instrucciones por reloj, haciendo que cualquier medida basada en el conteo de ciclos de reloj ejecute un bloque de instrucciones altamente inexacto.

Las frecuencias de CPU también son variables en función de la carga y/o temperatura ofrecidas. El hecho de que la CPU se esté ejecutando actualmente a 800 MHz no significa que siempre estará funcionando a 800 MHz, sino que podría acelerarse hacia arriba o hacia abajo según sea necesario.

Si realmente necesita saber la frecuencia del reloj, se debe pasar como un parámetro. Una EEPROM en la placa suministraría la frecuencia base, y si el reloj puede variar, necesitaría poder leer los registros de estado de alimentación de la CPU (o hacer una llamada al sistema operativo) para averiguar la frecuencia en ese instante.

Con todo lo dicho, puede haber otras formas de lograr lo que estás tratando de hacer. Por ejemplo, si quiere hacer mediciones de alta precisión de cuánto tiempo tarda una determinada ruta de codificación, es probable que la CPU tenga contadores de rendimiento que funcionen a una frecuencia fija que son una mejor medida del tiempo de la pared que leer un registro de conteo de marcas.

15

CPU Intel después de que Core Duo admita dos registros específicos del modelo llamados IA32_MPERF y IA32_APERF.
MPERF cuenta a la frecuencia máxima que admite la CPU, mientras que APERF cuenta a la frecuencia actual real.

La frecuencia real viene dada por:

freq = max_frequency * APERF/MPERF

Se pueden leer con este flujo

; read MPERF 
mov ecx, 0xe7 
rdmsr 
mov mperf_var_lo, eax 
mov mperf_var_hi, edx 

; read APERF 
mov ecx, 0xe8 
rdmsr 
mov aperf_var_lo, eax 
mov aperf_var_hi, edx 

pero tenga en cuenta que rdmsr es una instrucción privilegiada y sólo se puede ejecutar en el anillo 0.

No sé si el sistema operativo proporciona una interfaz para leer estos, aunque su uso principal es para la administración de energía, por lo que podría no proporcionar tal interfaz

+0

genial!¿Cómo hiciste la ecuación tan agradable? –

+3

Utilicé este sitio para convertir el código LaTeX a GIF: http://en.wikibooks.org/wiki/LaTeX/Mathematics. La sintaxis de LaTeX para las matemáticas se describe aquí: http://en.wikibooks.org/wiki/LaTeX/Mathematics. –

+1

Vaya, el primer sitio debe ser http://texify.com/. –

6

Voy a la fecha a mí mismo con varios detalles en esta respuesta, pero qué diablos ...

que tuvieron que hacer frente a este problema hace años en los ordenadores basados ​​en Windows, por lo que estaba tratando con la serie x86 de Intel procesadores como 486, Pentium, etc. El algoritmo estándar en esa situación era hacer una larga serie de instrucciones DIVide, porque esas son, por lo general, las instrucciones más vinculadas a la CPU en el conjunto de Intel. Por lo tanto, la captación previa de memoria y otros problemas arquitectónicos no afectan materialmente el tiempo de ejecución de la instrucción: la cola de captación previa siempre está llena y la instrucción en sí no toca ninguna otra memoria.

Lo cronometrarías usando el reloj de mayor resolución al que pudieras acceder en el entorno en el que te estás ejecutando. (En mi caso, estaba funcionando cerca de un PC compatible, así que estaba programando directamente las fichas del temporizador la placa baseNo se recomienda en un sistema operativo real, por lo general hay alguna API adecuada para llamar en estos días).

El problema principal que tiene que tratar es diferentes tipos de CPU. En ese momento, Intel, AMD y algunos proveedores más pequeños como Cyrix fabricaban procesadores x86. Cada modelo tenía sus propias características de rendimiento en comparación con la instrucción DIV. Mi función de sincronización de ensamblaje simplemente devolvería una cantidad de ciclos de reloj tomados por una cierta cantidad fija de instrucciones DIV hechas en un ciclo cerrado.

Así que lo que hice fue recopilar algunos tiempos (valores de retorno sin procesar de esa función) de PC reales que ejecutaban cada modelo de procesador que quería cronometrar, y registrarlos en una hoja de cálculo contra la velocidad de procesador y el tipo de procesador conocidos. De hecho, tenía una herramienta de línea de comandos que era solo un delgado caparazón alrededor de mi función de sincronización, y me gustaría llevar un disco a las tiendas de informática y obtener los tiempos de los modelos de visualización. (Trabajé para una compañía muy pequeña en ese momento).

Utilizando esos tiempos sin procesar, podría trazar un gráfico teórico de los tiempos que debería obtener para cualquier velocidad conocida de esa CPU en particular.

Aquí estaba el truco: siempre odié cuando ejecutabas una utilidad y anunciaba que tu CPU era de 99.8 Mhz o lo que sea. Claramente, era de 100 Mhz y solo había un pequeño error de redondeo en la medición. En mi hoja de cálculo grabé las velocidades reales que vendía cada proveedor de procesadores. Luego utilizaría la trama de los tiempos reales para estimar los tiempos proyectados para cualquier velocidad conocida. Pero construiría una tabla de puntos a lo largo de la línea donde los tiempos deberían redondearse a la siguiente velocidad.

En otras palabras, si 100 tics para hacer toda esa división repetitiva significaban 500 Mhz, y 200 tics significaban 250 Mhz, entonces construiría una tabla que dijera que cualquier valor inferior a 150 era 500 Mhz, y cualquier valor superior a 250 Megahercio. (Suponiendo que esas fueran las únicas dos velocidades disponibles de ese proveedor de chips). Fue agradable, porque incluso si alguna pieza extraña de software en la PC estuviese interrumpiendo mis tiempos, el resultado final a menudo seguiría sin funcionar.

Por supuesto ahora, en estos días de overclocking, velocidades de reloj dinámicas para la administración de energía, y otros trucos como ese, un esquema sería mucho menos práctico. Por lo menos, necesitaría hacer algo para asegurarse de que la CPU estaba en su velocidad más alta elegida dinámicamente antes de ejecutar su función de temporización.

Bien, volveré a espantar a los niños de mi jardín ahora.

+2

Diría que una velocidad de 99.8 podría ser precisa, estaban * apuntando * a 100Mhz pero se perdieron. No espere que eliminen los chips del sistema que están un poco fuera de tiempo como lo haría con los relojes de pulsera. –

+1

Estoy de acuerdo. No solo tiene la teoría del objetivo, sino que también tiene factores que le permiten esperar un nivel de fluctuaciones en una computadora. Las placas base realmente absorben una cantidad fluctuante de voltajes. Una CPU de "100 MHz" también podría ser una CPU de 25 MHz con un multiplicador 4x o 33 MHz con un multiplicador 3x –

0

Un google rápido en AMD y Intel muestra que la CPUID debería darle acceso a la frecuencia máxima de la CPU.

+0

Creo que solo identificará el modelo de procesador. –

1

"lmbench" proporciona un algoritmo de frecuencia de CPU portátil para diferentes arquitecturas.

Ejecuta algunos bucles diferentes y la velocidad de reloj del procesador es el mayor divisor común de las frecuencias de ejecución de los diversos bucles.

este método siempre debe funcionar cuando podemos obtener bucles con recuentos de ciclos relativamente primos.

http://www.bitmover.com/lmbench/

4

Una forma en x86 de Intel CPU de desde Pentium sería utilizar dos muestreos de la instrucción RDTSC con un bucle de retardo de tiempo de pared conocido, por ejemplo:

#include <stdio.h> 
#include <stdint.h> 
#include <unistd.h> 

uint64_t rdtsc(void) { 
    uint64_t result; 
    __asm__ __volatile__ ("rdtsc" : "=A" (result)); 
    return result; 
} 

int main(void) { 
    uint64_t ts0, ts1;  
    ts0 = rdtsc(); 
    sleep(1); 
    ts1 = rdtsc();  
    printf("clock frequency = %llu\n", ts1 - ts0); 
    return 0; 
} 

(en 32 bits plataformas con GCC)

RDTSC está disponible en el anillo 3 si se establece el indicador TSC en CR4, que es común pero no está garantizado. Una deficiencia de este método es que es vulnerable a los cambios de escala de frecuencia que afectan el resultado si ocurren dentro de la demora. Para mitigarlo, podría ejecutar código que mantenga ocupada la CPU y consultar constantemente la hora del sistema para ver si su período de retraso ha expirado, para mantener la CPU en el estado de frecuencia más alta disponible.

+0

RDTSC cuenta los "ciclos de referencia" en las CPU modernas, no en los ciclos del reloj central. Por lo tanto, esto determinará la frecuencia de reloj "clasificada"/máxima sostenida en la mayoría de las CPU modernas, no en los relojes actuales. Esto puede ser lo que realmente desea, excepto en sistemas overclockeados que se ejecutan a una velocidad diferente de forma permanente. –

2

utilizo el siguiente (pseudo) algoritmo:

basetime=time(); /* time returns seconds */ 

while (time()==basetime); 
stclk=rdtsc(); /* rdtsc is an assembly instruction */ 

basetime=time(); 
while (time()==basetime 
endclk=rdtsc(); 

nclks=encdclk-stclk; 

En este punto se puede asumir que usted ha determinado la frecuencia de reloj, pero a pesar de que parece correcto que se puede mejorar.

Todas las PC contienen un dispositivo PIT (Temporizador programable programable) que contiene contadores que se utilizan (solían usarse) para puertos serie y el reloj del sistema. Fue alimentado con una frecuencia de 1193182 Hz. El contador del reloj del sistema se estableció en el valor de cuenta regresiva más alto (65536), lo que da como resultado una frecuencia de marcación del reloj del sistema de 1193182/65536 => 18.2065 Hz o una vez cada 54.925 milisegundos.

Por lo tanto, dependerá del número de tics necesarios para que el reloj incremente al siguiente segundo. Por lo general, se requieren 18 ticks y, a veces, 19. Esto se puede manejar ejecutando el algoritmo (arriba) dos veces y almacenando los resultados. Los dos resultados serán equivalentes a dos secuencias de 18 ticks o una 18 y una 19. No se producirán dos 19 seguidos. Entonces, al tomar el menor de los dos resultados, tendrá un segundo punto de 18 ticks. Ajuste este resultado multiplicándolo por 18.2065 y dividiendo por 18.0 o, usando la aritmética de números enteros, multiplique por 182065, agregue 90000 y divida por 180000. 90000 es la mitad de 180000 y está ahí para redondear. Si elige el cálculo con una ruta entera, asegúrese de estar usando multiplicación y división de 64 bits.

Ahora tendrá una velocidad de reloj de la CPU x en Hz que se puede convertir a kHz ((x + 500)/1000) o MHz ((x + 5000000)/1000000). Los 500 y 500000 son la mitad de 1000 y 1000000 respectivamente y están ahí para redondear. Para calcular MHz, no pase por el valor kHz porque pueden surgir problemas de redondeo. Use el valor de Hz y el segundo algoritmo.

0

Una opción es detectar la frecuencia de la CPU, mediante la ejecución de código con instrucciones conocidas por bucle

Esta funcionalidad está contenida en 7zip, ya que alrededor v9.20 creo.

> 7z b 
7-Zip 9.38 beta Copyright (c) 1999-2014 Igor Pavlov 2015-01-03 

CPU Freq: 4266 4000 4266 4000 2723 4129 3261 3644 3362 

El número final está destinado a ser correcta (y en mi PC y muchos otros, he encontrado que es bastante correcto - la prueba corre muy rápido, así turbo no puede arrancar, y los servidores establecido en Balanced/modos de ahorro de energía más probable es que dan lecturas de alrededor de 1 GHz)

el código fuente está en GitHub (fuente oficial es una descarga de 7-zip.org)

Con la parte más importante ser:

#define YY1 sum += val; sum ^= val; 
#define YY3 YY1 YY1 YY1 YY1 
#define YY5 YY3 YY3 YY3 YY3 
#define YY7 YY5 YY5 YY5 YY5 
static const UInt32 kNumFreqCommands = 128; 

EXTERN_C_BEGIN 

static UInt32 CountCpuFreq(UInt32 sum, UInt32 num, UInt32 val) 
{ 
    for (UInt32 i = 0; i < num; i++) 
    { 
    YY7 
    } 
    return sum; 
} 

EXTERN_C_END 
Cuestiones relacionadas