¿Qué tan grande es n?
La programación predeterminada para una directiva OpenMP parallel for
es específica de la implementación. Parece que en GOMP (la implementación OpenMP utilizada por gcc), el valor predeterminado es (dynamic,1)
de acuerdo con documentation here. Esto significa que cada subproceso está accediendo (en i-1
y i+1
) a ubicaciones de memoria cargadas por subprocesos vecinos, lo que podría provocar una utilización de memoria caché deficiente. En las arquitecturas de CPU modernas, las operaciones de esténciles como esta suelen estar unidas a la memoria y son sensibles al almacenamiento en caché. Usted podría tratar de especificar un horario con trozos más grandes, por ejemplo, mediante:
#pragma omp parallel for schedule(dynamic,1024)
sólo estoy usando 1024 como ejemplo. En la práctica, debe experimentar para encontrar el factor de fragmentación óptimo (o buscar sistemáticamente con un barrido de parámetros, un proceso que a menudo se denomina "autoajuste"). O puede elegir un valor basado más en teoría, por ejemplo derivandolo del tamaño de caché L1 o L2 de su CPU.
O podría intentar la programación estática, ya que la cantidad de computación dentro del bucle for es uniforme entre los hilos, y la sobrecarga del planificador dinámico puede estar causando un cuello de botella. Si especifica
#pragma omp parallel for schedule(static)
sin tamaño del trozo, a continuación, cada hilo se asignará un único trozo de aproximadamente el mismo tamaño.
Finalmente, es posible que también desee fijar los hilos OpenMP a sus propios núcleos de CPU. Puede hacerlo utilizando la variable de entorno GOMP_CPU_AFFINITY.
Editar:
sólo estaba jugando con el siguiente programa de prueba compilado con gcc 4.2.1, y creo que la documentación he vinculado al anterior es incorrecta. Parece que GOMP está predeterminado en schedule(static)
.
#include <stdio.h>
#include <omp.h>
int main(int argc, char** argv)
{
int i;
#pragma omp parallel for
for (i=0; i<15; i++) {
int id = omp_get_thread_num();
printf("%d assigned to thread %d\n", i, id);
}
}
Y la salida con dos hilos es:
$ ./test_sched | sort -n
0 assigned to thread 0
1 assigned to thread 0
2 assigned to thread 0
3 assigned to thread 0
4 assigned to thread 0
5 assigned to thread 0
6 assigned to thread 0
7 assigned to thread 0
8 assigned to thread 1
9 assigned to thread 1
10 assigned to thread 1
11 assigned to thread 1
12 assigned to thread 1
13 assigned to thread 1
14 assigned to thread 1
Compila y ejecuta bien con GCC 4.6.1. ¿Qué compilador usas? –
¿Puede agregar algunos detalles sobre el compilador y el sistema operativo? – talonmies
gcc 4.2.1 en MacOS Snow Leopard, precisamente: 686-apple-darwin10-g ++ - 4.2.1 (GCC) 4.2.1 (Apple Inc. compilación 5666) (punto 3) – Chris