Ricerca…


Osservazioni

OpenMP (Open MultiProcessing) è un modello di programmazione parallelo basato su direttive del compilatore che consente agli sviluppatori di applicazioni di aggiungere in modo parallelo il parallelismo ai loro codici applicativi.

Le specifiche API OpenMP per la programmazione parallela forniscono un'interfaccia API (Application Programming Interface) che supporta la programmazione multiprocessore multi-piattaforma di memoria condivisa in C, C ++ e Fortran, sulla maggior parte delle piattaforme. Consiste in un insieme di direttive del compilatore, routine di libreria e variabili di ambiente che influenzano il comportamento in fase di esecuzione.

Poichè OpenMP si concentra sul parallelismo all'interno di un nodo (multiprocessing della memoria condivisa) può essere combinato con modelli di programmazione che trasmettono messaggi, come MPI, da eseguire su più nodi.

Versioni

Versione linguaggio Data di rilascio
4.5 C / C ++ / Fortran 2015/11/01
4.0 C / C ++ / Fortran 2013/07/01
3.1 C / C ++ / Fortran 2011-07-01
3.0 C / C ++ / Fortran 2008-05-01
2.5 C / C ++ / Fortran 2005-05-01
2.0c C / C ++ 2002/03/01
2.0f Fortran 2000/11/01
1.0c C / C ++ 1998/10/01
1.0f Fortran 1997/10/01

Compilazione

Esistono molti compilatori che supportano diverse versioni delle specifiche OpenMP. OpenMP mantiene qui un elenco con il compilatore che lo supporta e la versione supportata. In generale, per compilare (e collegare) un'applicazione con il supporto di OpenMP è sufficiente aggiungere un flag di compilazione e se si utilizza l'API di OpenMP è necessario includere l'intestazione di OpenMP (omp.h). Mentre il file di intestazione ha un nome fisso, il flag di compilazione dipende dal compilatore. Di seguito è riportato un elenco non esaustivo di compilatori e il flag che abilita OpenMP.

  • GCC (inclusi gcc, g ++ e gfortran): -fopenmp
  • LLVM: -fopenmp
  • Intel compiler-suite (compresi icc, icpc e ifort): -qopenmp (e -fopenmp per compatibilità con GCC / LLVM)
  • Compilitore-suite IBM XL (inclusi xlc, xlC e xlf): -xlsmp=omp
  • Compiler-suite PGI (incluso pgcc pgc ++ pgfortran): '-mp'

Mondo ciao parallelo usando OpenMP

#include <omp.h>
#include <stdio.h>

int main (int argc, char *argv[])
{
   #pragma omp parallel
   {
     printf ("Hello world! I'm thread %d out of %d threads.\n",
             omp_get_thread_num(), omp_get_num_threads());
   }
   return 0;
}

Questo codice crea semplicemente un gruppo di thread (in base alla variabile di ambiente OMP_NUM_THREADS e, se non definito, ne creerà uno per ogni nodo logico sul sistema) e ciascun thread si identificherà oltre a stampare il tipico messaggio Hello world.

Costrutto di condivisione del lavoro - Esempio di ciclo For

double  res[MAX];  int i;
#pragma omp parallel 
{    
    #pragma omp for
    for (i=0;i< MAX; i++) {
        res[i] = huge();
    } 
}    

Il ciclo for verrà eseguito in parallelo. huge () è un metodo che può richiedere troppo tempo per essere eseguito. OpenMP supporta un collegamento per scrivere il codice sopra come:

double  res[MAX];  int i;
#pragma omp parallel for
for (i=0;i< MAX; i++) {
    res[i] = huge();
} 

Possiamo anche avere una clausola schedule che influenza il modo in cui le iterazioni del ciclo sono mappate ai thread. Per esempio:

#pragma omp parallel
#pragma omp for schedule(static)
for(i=0;I<N;i++) {
    a[i] = a[i] + b[i];
}

Diversi stili di pianificazione sono:

schedule (static [, chunk])
Distribuire blocchi di iterazioni di dimensioni "blocchi" a ciascun thread.
Se non specificato: allocare il più uniformemente possibile ai thread disponibili

pianificazione (dinamico [, chunk])
Ogni thread estrae le iterazioni "chunk" da una coda fino a quando tutte le iterazioni sono state gestite.

pianificazione (guidato [, chunk])
I thread afferrano dinamicamente blocchi di iterazioni. La dimensione del blocco inizia grande e si riduce a dimensioni "pezzo" come procede il calcolo.

programma (runtime)
Pianificazione e dimensione del blocco presa dalla variabile di ambiente OMP_SCHEDULE.

Esempio di riduzione

#include <omp.h>
void main ()
{     
    int i;       
    double ZZ, func(), res=0.0;

    #pragma omp parallel for reduction(+:res) private(ZZ) 
    for (i=0; i< 1000; i++){
        ZZ = func(I);
        res = res + ZZ; 
    }
}

Nell'ultima riga: aggiunta effettivamente a una copia privata, quindi combinata dopo il ciclo. Il compilatore si prende cura dei dettagli.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow