(1) Anidado en el paralelismo OpenMP: http://docs.oracle.com/cd/E19205-01/819-5270/aewbc/index.html
Es necesario activar el paralelismo anidado estableciendo OMP_NESTED
o omp_set_nested
porque muchas implementaciones desactivar esta función por defecto, aunque algunas implementaciones no apoyaron plenamente el paralelismo anidado . Si está activado, siempre que se encuentre con parallel for
, OpenMP creará la cantidad de hilos definidos en OMP_NUM_THREADS
. Entonces, si el paralelismo de 2 niveles, el número total de hilos sería N^2, donde N = OMP_NUM_THREADS
.
Tal paralelismo anidado causará sobresuscripción, (es decir, el número de hilos ocupados es mayor que los núcleos), lo que puede degradar la aceleración. En un caso extremo, donde el paralelismo anidado se llama de manera recursiva, los hilos pueden estar hinchados (por ejemplo, creando hilos de 1000s), y la computadora simplemente pierde el tiempo para el cambio de contexto. En tal caso, puede controlar el número de subprocesos dinámicamente configurando omp_set_dynamic
.
(2) Un ejemplo de multiplicación de la matriz-vector: el código se vería así:
// Input: A(N by M), B(M by 1)
// Output: C(N by 1)
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
C[i] += A[i][j] * B[j];
En general, la paralelización de bucles internos mientras que los bucles exteriores son posibles es malo debido a la bifurcación/unión por encima de los hilos. (aunque muchas implementaciones OpenMP preproducen hilos, todavía requiere que algunos despachen tareas a hilos y para invocar barreras implícitas al final de paralelo-for)
Su preocupación es el caso de dónde N < # de CPU. Sí, claro, en este caso, la aceleración estaría limitada por N, y dejar que el paralelismo anidado definitivamente tenga beneficios.
Sin embargo, entonces el código provocaría sobresuscripción si N es suficientemente grande. Solo estoy pensando en las siguientes soluciones:
- Cambiando la estructura del bucle de modo que exista solo un bucle de 1 nivel.(Parece posible)
- Especializando el código: si N es pequeño, haga el paralelismo anidado; de lo contrario, no haga eso.
- paralelismo anidado con
omp_set_dynamic
. Pero, por favor, asegúrese de que omp_set_dynamic
controla el número de subprocesos y la actividad de los subprocesos. Las implementaciones pueden variar.
La manera de tratar con N pequeña sin poner el paralelismo un nivel bajo es solo usar colapso; '#pragma omp parallel for colapso'; 'for (int i = 0; i
Quizás algo de confusión. Estoy hablando de paralelismo anidado: Tener bucles paralelos anidados provocará la sobresuscripción. Si N es igual o mayor que la cantidad de núcleos (digamos n), se crearán n subprocesos en el bucle for-i externo. Luego, cada hilo bifurcará otros n hilos cuando el hilo se encuentre con el bucle for-j. Entonces, n * n hilos están trabajando en n núcleos. Puede verificarlo fácilmente utilizando las utilidades del sistema. – minjang
Ok, es suficiente, y eso es lo que preguntó.Pero, por supuesto, uno no haría eso; para eso es exactamente el colapso: paralelice sobre ambos bucles sin incurrir en la sobrecarga. –