2010-02-06 10 views
14

Tengo un administrador de montón de memoria que divide el montón en diferentes segmentos según la cantidad de procesadores en el sistema. La memoria solo se puede asignar en la partición que acompaña al procesador del hilo que se está ejecutando actualmente. Esto ayudará a permitir que diferentes procesadores continúen funcionando incluso si dos diferentes quieren asignar memoria al mismo tiempo, al menos eso creo.¿Cómo puede encontrar el número de procesador en el que se está ejecutando un subproceso?

He encontrado la función GetCurrentProcessorNumber() para Windows, pero esto solo funciona en Windows Vista y posterior. ¿Hay algún método que funcione en Windows XP?

Además, ¿se puede hacer esto con pthreads en un sistema POSIX?

+0

¿sabe usted que la mayoría de los sistemas operativos programarán el mismo hilo en diferentes núcleos a lo largo del tiempo? – PlasmaHH

Respuesta

8

Para XP, un rápido Google como reveló esto: https://www.cs.tcd.ie/Jeremy.Jones/GetCurrentProcessorNumberXP.htm ¿Esto ayuda?

+0

Sí, gracias. Esto parece funcionar tanto en Linux como en Windows, siempre que se ejecute en una plataforma x86. –

+0

@Patrick No creo que esto funcione en Linux, solo XP en esa forma de todos modos. –

+0

El lenguaje de ensamblaje en sí no depende de los sistemas operativos. En cuanto a la diferencia entre _asm, '__asm__', asm, etc. en diferentes plataformas y compiladores, puedo lidiar con eso. –

9

Desde la salida de man sched_getcpu:

NAME 
     sched_getcpu - determine CPU on which the calling thread is running 

SYNOPSIS 
     #define _GNU_SOURCE 
     #include <utmpx.h> 

     int sched_getcpu(void); 

DESCRIPTION 
    sched_getcpu() returns the number of the CPU 
    on which the calling thread is currently executing. 

RETURN VALUE 
    On success, sched_getcpu() returns a non-negative CPU number. 
    On error, -1 is returned and errno is set to indicate the error. 

SEE ALSO 
    getcpu(2) 

Por desgracia, esto es específico de Linux. Dudo que haya una manera portátil de hacer esto.

+0

Una lectura rápida de la documentación de pthread no revela ninguna llamada que forme parte de la API phtread que hace esto. – Omnifarious

+0

Gracias Ilia. Aunque esto solo funciona en Linux, es una llamada de función agradable y limpia. Si/cuando necesito realizar un puerto a otro kernel, puedo simplemente cambiar esta llamada de función a una versión modificada del ensamblador anterior. –

0

Este diseño me huele mal. Parece que está asumiendo que un hilo permanecerá asociado a una CPU específica. Eso no está garantizado Sí, un hilo normalmente puede permanecer en una sola CPU, pero no tiene que ser así, y eventualmente su programa tendrá un hilo que cambiará la CPU. Puede no suceder a menudo, pero finalmente lo hará. Si su diseño no tiene esto en cuenta, es probable que tarde o temprano golpee algún tipo de error difícil de rastrear.

Déjame hacerte esta pregunta, ¿qué ocurre si la memoria se asigna en una CPU y se libera en otra? ¿Cómo manejará tu montón eso?

+0

El procesador de liberación no importa. En cada bloque, guardo un puntero a la partición correcta. Solo llamo a la función una vez por asignación, así que esto no es un problema. Si bien es cierto que el hilo actual puede cambiar los procesadores, esto tampoco daría lugar a ningún problema con mi diseño (en teoría: P). El montón en sí mismo sigue siendo un montón cerrado. Entonces, si dos hilos diferentes quieren asignar en la misma partición, uno será bloqueado hasta que el otro termine. Este diseño solo minimiza la posibilidad de que un procesador bloquee la ejecución de otro. –

+0

El problema es, presumiblemente, que un hilo puede migrar _while_ asignando memoria. Esto puede provocar que un subproceso determine que se ejecuta en la CPU n. ° 0, obtener un puntero al n. ° 0, luego migrar a la CPU n. ° 1 y luego intentar asignar desde el n. ° 0. – MSalters

+0

Eso está bien. Mi montón es un montón bloqueado, así que incluso sin este número de procesador de magia negra, funcionaría bien. Lo estoy optimizando para no bloquear otros procesadores que podrían ser algo más útil. Entonces, en el caso de que ambos señalaran, otro procesador estará bloqueado de la asignación. El punto principal de mi diseño, sin embargo, es que esto es más improbable que suceda, por lo que vale la pena el esfuerzo. –

1

Si todo lo que quiere hacer es evitar la contención, no necesita conocer la CPU actual. Podrías elegir aleatoriamente un montón. O podrías tener un montón por hilo. Aunque puede obtener más o menos contención de esa manera, evitaría la sobrecarga de sondear la CPU actual, que puede o no ser significativa. También consulte el scalable_allocator de Intel Thread Building Block, que ya puede haber resuelto ese problema mejor que usted.

3

Además de la respuesta de Antony Vennard y el código en el sitio citado, aquí está el código que va a trabajar para Visual C++ x64 así (sin línea ensamblador):

DWORD GetCurrentProcessorNumberXP() { 
    int CPUInfo[4]; 
    __cpuid(CPUInfo, 1); 
    // CPUInfo[1] is EBX, bits 24-31 are APIC ID 
    if ((CPUInfo[3] & (1 << 9)) == 0) return -1; // no APIC on chip 
    return (unsigned)CPUInfo[1] >> 24; 
} 

Un breve vistazo a la implementación de GetCurrentProcessorNumber() en Win7 x64 muestra que usan un mecanismo diferente para obtener el número de procesador, pero en mis (pocas) pruebas los resultados fueron los mismos para mi casa y la función oficial.

+0

Cpuid es una instrucción de serialización y extremadamente costosa (piense en 1000 ciclos). Ciertamente no es una elección adecuada para el propósito discutido aquí. Escoger un montón al azar sería mejor, suponiendo que no gaste 1000 ciclos en el generador de números :-) –

Cuestiones relacionadas