2012-02-21 16 views
7

Actualmente estoy paralelizando el programa usando openmp en un fenómeno de 4 núcleos. Sin embargo, noté que mi paralelización no hace nada por el rendimiento. Naturalmente, asumí que me perdí algo (intercambio de falsos, serialización a través de bloqueos, ...), sin embargo, no pude encontrar algo así. Además de la utilización de la CPU, parecía que el programa se ejecutó solo en un núcleo. De lo que encontré sched_getcpu() debería darme el ID del núcleo en el que está actualmente programado el hilo que está ejecutando la llamada. Así que escribí el siguiente programa de prueba:Hilos OpenMP ejecutándose en el mismo núcleo de la CPU

#include <iostream> 
#include <sstream> 
#include <omp.h> 
#include <utmpx.h> 
#include <random> 
int main(){ 
    #pragma omp parallel 
    { 
     std::default_random_engine rand; 
     int num = 0; 
    #pragma omp for 
     for(size_t i = 0; i < 1000000000; ++i) num += rand(); 
    auto cpu = sched_getcpu(); 
    std::ostringstream os; 
     os<<"\nThread "<<omp_get_thread_num()<<" on cpu "<<sched_getcpu()<<std::endl; 
     std::cout<<os.str()<<std::flush; 
    std::cout<<num; 
    } 
} 

En mi máquina esto da el siguiente resultado (los números aleatorios variarán por supuesto):

Thread 2 on cpu 0 num 127392776 
Thread 0 on cpu 0 num 1980891664 
Thread 3 on cpu 0 num 431821313 
Thread 1 on cpu 0 num -1976497224 

De esta Asumo que todos los hilos se ejecutan en el mismo núcleo (el que tiene id 0). Para estar más seguro, también probé el enfoque desde this answer. Los resultados fueron los mismos. Además, el uso de #pragma omp parallel num_threads(1) no hizo que la ejecución fuera más lenta (de hecho, un poco más rápida), lo que dio credibilidad a la teoría de que todos los subprocesos utilizan la misma CPU, sin embargo, el hecho de que la CPU se muestra siempre como 0 me hace sospechar. Además, revisé GOMP_CPU_AFFINITY que inicialmente no estaba configurado, así que intenté configurarlo en 0 1 2 3, lo que debería vincular cada hilo a un núcleo diferente de lo que yo entiendo. Sin embargo, eso no hizo la diferencia.

Desde que desarrollo en un sistema de Windows, uso linux en virtualbox para mi desarrollo. Entonces pensé que tal vez el sistema virtual no podía acceder a todos los núcleos. Sin embargo, comprobar la configuración de virtualbox mostró que la máquina virtual debería obtener los 4 núcleos y ejecutar mi programa de prueba 4 veces al mismo tiempo parece usar los 4 núcleos a juzgar por la utilización de la CPU (y el hecho de que el sistema no respondía) .

Así que mi pregunta es básicamente qué está pasando exactamente aquí. Más al grano: ¿Debo deducir que todos los hilos utilizan el mismo núcleo correctamente? Si lo es, ¿cuáles podrían ser las razones de ese comportamiento?

+1

heres un error común ¿configuró la variable de entorno OMP_NUM_THREADS = 4? – pyCthon

+0

@pyCthon: 'OMP_NUM_THREADS' no parece estar configurado, sin embargo, como openmp crea 4 hilos, no creo que sea necesario. – Grizzly

+0

raro, creo que podría ser algo con su máquina virtual Probé el mismo código incluso instalé utmpx.h y parecía funcionar bien en una máquina de 8 y 16 núcleos – pyCthon

Respuesta

6

Después de un poco de experimentación, descubrí que el problema era que estaba iniciando mi programa desde el eclipse IDE, que aparentemente configuraba la afinidad para usar solo un núcleo. Pensé que tenía los mismos problemas cuando comencé desde fuera del IDE, pero una prueba repetida mostró que el programa funciona bien, cuando se inicia desde la terminal en lugar de desde el ide.

0

Debe utilizar #pragma omp parallel for
Y sí, tienes razón en no necesitar OMP_NUM_THREADS. omp_set_num_threads(4); también debería haberlo hecho bien.

+0

¿Por qué debería usar '#pragma omp parallel for', si quiero que los hilos hagan cosas fuera del ciclo (como escribir su ID en la salida)? Y como mencioné, crea 4 subprocesos por defecto, los que simplemente parecen ejecutarse en el mismo núcleo – Grizzly

+0

Eso también es cierto. Por cierto, si no dice omp * parallel * for, entonces no ocurre la paralelización en el ciclo. Pero, por supuesto, estás dentro de una sección paralela, así que ... La única otra posible explicación que puedo pensar es la falta de soporte de hardware para tu virtualbox. ¿Has probado con otras CPU? http://superuser.com/questions/33723/getting-2-processors-to-work-with-virtualbox-on-dual-core-celeron – Nav

+0

No lo hice. Sin embargo, como se mencionó, es posible usar todos los núcleos de vbox, por lo que la falta de soporte parece poco probable. – Grizzly

0

si está ejecutando en Windows, intente esto:

c: \ windows \ system32 \ cmd.exe/C empiecen/F afinidad ruta \ a \ su \ program.exe

/afinidad 1 utiliza CPU0

/afinidad 2 utiliza CPU1

/afinidad 3 utiliza CPU0 y CPU1

/afinidad 4 utiliza CPU2

/afinidad F usa los 4 núcleos

Convierta el número a hexadecimal y vea los bits de la derecha que son los núcleos que se utilizarán.

puede verificar la afinidad mientras se ejecuta utilizando el administrador de tareas.

+0

El vbox tiene la afinidad correcta para usar todos los núcleos (comprobé y además ¿cómo usaría todos ellos en mi prueba con múltiples comienzo de mi programa de prueba). Ya que utilizo linux dentro de la vbox que realmente no ayuda allí. – Grizzly

1

He compilado su programa usando g ++ 4.6 en Linux

g++ --std=c++0x -fopenmp test.cc -o test 

La salida fue, como era de esperar:

Thread 2 on cpu 2 

Thread 3 on cpu 1 
910270973 
Thread 1 on cpu 3 
910270973 
Thread 0 on cpu 0 
910270973910270973 

El hecho de que se inician 4 hilos (si no se ha establecido el número de hilos de ninguna manera, por ejemplo, utilizando OMP_NUM_THREADS) debe implicar que el programa puede ver 4 CPU utilizables. No puedo adivinar por qué no los está usando, pero sospecho que hay un problema en la configuración de su hardware/software, en alguna variable de entorno o en las opciones del compilador.

Cuestiones relacionadas