Diferencia entre #pragma omp paralelo y #pragma omp paralelo para

Dec 11 2020

Soy nuevo OpenMPy he intentado ejecutar un programa que agrega dos matrices usando OpenMP. En el tutorial de OpenMP, aprendí que necesitamos usar #pragma omp paralelo mientras usamos OpenMP en el bucle for . Pero también he intentado lo mismo con #pragma omp paralelo y también me está dando el resultado correcto. A continuación se muestran los fragmentos de código de lo que estoy tratando de transmitir.

#pragma omp parallel for
{
      for(int i=0;i<n;i++)
       {  
            c[i]=a[i]+b[i];
       }
}

y

 #pragma omp parallel
{
      for(int i=0;i<n;i++)
       {  
            c[i]=a[i]+b[i];
       }
}

¿Cuál es la diferencia entre estos dos?

Respuestas

5 dreamcrash Dec 11 2020 at 15:14

los

#pragma omp parallel:

creará un parallel regioncon un equipo de threads, donde cada hilo ejecutará todo el bloque de código que parallel regionencierra.

Desde OpenMP 5.1 se puede leer una descripción más formal:

Cuando un hilo encuentra una construcción paralela , se crea un equipo de hilos para ejecutar la región paralela (..). El hilo que encontró la construcción paralela se convierte en el hilo principal del nuevo equipo, con un número de hilo de cero durante la duración de la nueva región paralela. Todos los hilos del nuevo equipo, incluido el hilo principal, ejecutan la región. Una vez que se crea el equipo, el número de subprocesos en el equipo permanece constante durante la duración de esa región paralela.

Los:

#pragma omp parallel for

creará un parallel region(como se describió anteriormente), y al threadsde esa región se asignarán las iteraciones del bucle que encierra, utilizando el default chunk size, y el default scheduleque normalmente es static. Sin embargo, default scheduletenga en cuenta que pueden diferir entre diferentes implementaciones concretas de la OpenMPnorma.

Desde OpenMP 5.1 puede leer una descripción más formal:

La construcción de bucle de trabajo compartido especifica que las iteraciones de uno o más bucles asociados se ejecutarán en paralelo por los subprocesos del equipo en el contexto de sus tareas implícitas. Las iteraciones se distribuyen entre los subprocesos que ya existen en el equipo que está ejecutando la región paralela a la que se une la región del ciclo de trabajo compartido .

Además ,

La construcción de bucle paralelo es un atajo para especificar una construcción en paralelo que contiene una construcción de bucle con uno o más bucles asociados y ninguna otra declaración.

O informalmente, #pragma omp parallel fores una combinación del constructor #pragma omp parallelcon #pragma omp for. En su caso, esto significaría que:

#pragma omp parallel for
{
      for(int i=0;i<n;i++)
       {  
            c[i]=a[i]+b[i];
       }
}

es semántica y lógicamente lo mismo que:

#pragma omp parallel
{
      #pragma omp for
      for(int i=0;i<n;i++)
       {  
            c[i]=a[i]+b[i];
       }
}

TL; DR: En su ejemplo, con #pragma omp parallel forel bucle se paralelizará entre los hilos ( es decir, las iteraciones del bucle se dividirán entre los hilos), mientras que con #pragma omp parallel todos los hilos se ejecutarán (en paralelo) todas las iteraciones del bucle.

Para hacerlo más ilustrativo, con 4hilos el #pragma omp parallel, resultaría en algo como:

mientras que #pragma omp parallel forcon una chunk_size=1y una estática schedule resultaría en algo como:

En cuanto al código, el bucle se transformaría en algo lógicamente similar a:

for(int i=omp_get_thread_num(); i < n; i+=omp_get_num_threads())
{  
    c[i]=a[i]+b[i];
}

donde omp_get_thread_num ()

La rutina omp_get_thread_num devuelve el número de hilo, dentro del equipo actual, del hilo de llamada.

y omp_get_num_threads ()

Devuelve el número de subprocesos del equipo actual. En una sección secuencial del programa omp_get_num_threads devuelve 1.

o en otras palabras, for(int i = THREAD_ID; i < n; i += TOTAL_THREADS). Con un THREAD_IDrango de 0hasta TOTAL_THREADS - 1y TOTAL_THREADSrepresentando el número total de subprocesos del equipo creados en la región paralela.

Aprendí que necesitamos usar #pragma omp paralelo mientras usamos OpenMP en el ciclo for. Pero también he intentado lo mismo con #pragma omp paralelo y también me está dando el resultado correcto.

Te da el mismo resultado, porque en tu código:

 c[i]=a[i]+b[i];

matriz ay matriz bsolo se leen, y matriz c[i]es la única que se actualiza, y su valor no depende de cuántas veces ise ejecutará la iteración . Sin embargo, con #pragma omp parallel forcada hilo se actualizará el suyo i, mientras que con los #pragma omp parallelhilos se actualizarán los mismos is, por lo que se anularán los valores de los demás.

Ahora intente hacer lo mismo con el siguiente código:

#pragma omp parallel for
{
      for(int i=0;i<n;i++)
       {  
            c[i]= c[i] + a[i] + b[i];
       }
}

y

#pragma omp for
{
      for(int i=0;i<n;i++)
       {  
            c[i] = c[i] + a[i] + b[i];
       }
}

Inmediatamente notará la diferencia.

2 DanielLangr Dec 11 2020 at 15:16

En el segundo caso, el bucle no está en paralelo. Es decir, el ciclo completo se ejecuta en cada hilo . Generalmente, lo que está dentro de la región paralela es ejecutado por todos los subprocesos.

Además, puede paralelizar el bucle en la región paralela ya existente de la siguiente manera:

#pragma omp parallel
{
  #pragma omp for
  for (int i = 0; i < n; i++)
    c[i] = a[i] + b[i];
}