usar plantillas fluir con como asana c parallel-processing openmp

plantillas - fluir con asana



Diferencia entre sección y tarea. (1)

La diferencia entre las tareas y las secciones está en el marco de tiempo en el que se ejecutará el código. Las secciones están incluidas dentro de la construcción de sections y (a menos que se haya especificado la cláusula nowait ), los hilos no lo abandonarán hasta que se hayan ejecutado todas las secciones:

[ sections ] Thread 0: -------< section 1 >---->*------ Thread 1: -------< section 2 >*------ Thread 2: ------------------------>*------ ... * Thread N-1: ---------------------->*------

Aquí N hilos encuentran una construcción de sections con dos secciones, la segunda toma más tiempo que la primera. Los dos primeros hilos ejecutan una sección cada uno. Los otros hilos N-2 simplemente esperan en la barrera implícita al final de la construcción de las secciones (se muestra aquí como * ).

Las tareas se ponen en cola y se ejecutan siempre que sea posible en los llamados puntos de programación de tareas. Bajo ciertas condiciones, el tiempo de ejecución podría permitir mover la tarea entre subprocesos, incluso en la mitad de su vida útil. Dichas tareas se llaman desatadas y una tarea desatada puede comenzar a ejecutarse en un subproceso, luego, en algún punto de la programación, el tiempo de ejecución puede migrar a otro subproceso.

Sin embargo, las tareas y secciones son en muchos aspectos similares. Por ejemplo, los siguientes dos fragmentos de código logran esencialmente el mismo resultado:

// sections ... #pragma omp sections { #pragma omp section foo(); #pragma omp section bar(); } ... // tasks ... #pragma omp single nowait { #pragma omp task foo(); #pragma omp task bar(); } #pragma omp taskwait ...

taskwait funciona como una barrier pero para las tareas: garantiza que el flujo de ejecución actual se detenga hasta que se ejecuten todas las tareas en cola. Es un punto de programación, es decir, permite que los subprocesos procesen tareas. La construcción single es necesaria para que las tareas sean creadas por un solo hilo. Si no hubiera single construcción single , cada tarea se crearía num_threads veces, lo que podría no ser lo que uno quiere. La cláusula nowait en el constructo single ordena a los otros subprocesos que no esperen hasta que se ejecutó el constructo single (es decir, elimina la barrera implícita al final del constructo single ). Así que llegan a la taskwait inmediatamente y comienzan a procesar las tareas.

taskwait es un punto de programación explícito que se muestra aquí para mayor claridad. También hay puntos de programación implícitos, sobre todo dentro de la sincronización de barrera, sin importar si son explícitos o implícitos. Por lo tanto, el código anterior también podría escribirse simplemente como:

// tasks ... #pragma omp single { #pragma omp task foo(); #pragma omp task bar(); } ...

Aquí hay un posible escenario de lo que podría suceder si hay tres hilos:

+--+-->[ task queue ]--+ | | | | | +-----------+ | | | Thread 0: --< single >-| v |----- Thread 1: -------->|< foo() >|----- Thread 2: -------->|< bar() >|-----

Mostrar aquí dentro de la | ... | | ... | es la acción del punto de planificación (ya sea la directiva de taskwait o la barrera implícita). Básicamente, los hilos 1 y 2 suspenden lo que están haciendo en ese punto y comienzan a procesar las tareas de la cola. Una vez que se han procesado todas las tareas, los hilos reanudan su flujo de ejecución normal. Tenga en cuenta que los subprocesos 1 y 2 pueden alcanzar el punto de programación antes de que el subproceso 0 haya salido de la construcción single , por lo que la izquierda | No es necesario que esté alineado (esto se representa en el diagrama anterior).

También puede suceder que el subproceso 1 pueda terminar de procesar la tarea foo() y solicitar otra incluso antes de que los otros subprocesos puedan solicitar tareas. Entonces, tanto foo() como bar() podrían ejecutarse en el mismo hilo:

+--+-->[ task queue ]--+ | | | | | +------------+ | | | Thread 0: --< single >-| v |--- Thread 1: --------->|< foo() >< bar() >|--- Thread 2: --------------------->| |---

También es posible que el subproceso individualizado pueda ejecutar la segunda tarea si el subproceso 2 llega demasiado tarde:

+--+-->[ task queue ]--+ | | | | | +------------+ | | | Thread 0: --< single >-| v < bar() >|--- Thread 1: --------->|< foo() > |--- Thread 2: ----------------->| |---

En algunos casos, el compilador o el tiempo de ejecución de OpenMP pueden incluso pasar por alto la cola de tareas por completo y ejecutar las tareas en serie:

Thread 0: --< single: foo(); bar() >*--- Thread 1: ------------------------->*--- Thread 2: ------------------------->*---

Si no hay puntos de programación de tareas presentes dentro del código de la región, el tiempo de ejecución de OpenMP puede iniciar las tareas cuando lo considere apropiado. Por ejemplo, es posible que todas las tareas se aplacen hasta que se alcance la barrera al final de la región parallel .

¿Cuál es la diferencia en OpenMP entre:

#pragma omp parallel sections { #pragma omp section { fct1(); } #pragma omp section { fct2(); } }

y:

#pragma omp parallel { #pragma omp single { #pragma omp task fct1(); #pragma omp task fct2(); } }

No estoy seguro de que el segundo código sea correcto ...