Diretiva parallel Diretiva parallel pragma omp parallel clauses
- Slides: 39
Diretiva parallel
Diretiva parallel #pragma omp parallel [clauses] { code_block } Define uma região paralela, que é o código que será executado por vários threads em paralelo.
// omp_parallel. cpp // compile with: /openmp Exemplo – Diretiva parallel #include <stdio. h> #include <omp. h> int main() { #pragma omp parallel num_threads(4) { int i = omp_get_thread_num(); printf_s("Hello from thread %dn", i); } }
Por padrão, o número de threads é igual ao número de processadores lógicos no computador. Diretiva parallel Por exemplo, se você tiver uma máquina com um processador físico com hyperthreading habilitado, ele terá dois processadores lógicos e, portanto, duas threads. Hyperthreading - Simulando dois núcleos lógicos em um único núcleo físico, cada núcleo lógico recebe seu próprio controlador de interrupção programável, e um conjunto de registradores. Os outros recursos do núcleo físico como cache de memória, unidade lógica e aritmética, barramentos, são compartilhados entre os núcleos lógicos, parecendo assim um sistema com dois núcleos físicos.
omp_get_thread_num() Retorna o número da thread em execução dentro de sua equipe de threads em paralelo. Função omp_get_thread_num() Hello from thread 0 Hello from thread 1 Hello from thread 2 Hello from thread 3 Observe que a ordem de saída pode variar em máquinas diferentes. Não confundir com omp_get_num_threads() função retorna o número de threads, atualmente na equipe de threads executando na região paralela do qual ele é chamado.
Diretiva Open. MP for
Diretiva Open. MP for #pragma omp [parallel] for [clauses] for_statement Faz com que o trabalho feito em um loop for dentro de uma região paralela seja dividido entre threads.
#pragma omp for (i = n. Start; i <= n. End; ++i) { #pragma omp atomic n. Sum += i; } Diretiva atomic - Especifica que um local de memória que será atualizado numa única etapa de processamento, relativa a outras threads. An operation acting on shared memory is atomic if it completes in a single step relative to other threads.
Operações agindo sobre memória compartilhada. Ver a diretiva Open. MP atomic
Diretiva master A diretiva master permite especificar que uma seção de código deve ser executada em uma única thread, não necessariamente a thread principal.
int main( ) { Exemplo – Diretivas master e barrier int a[5], i; #pragma omp parallel { // Perform some computation. #pragma omp for (i = 0; i < 5; i++) a[i] = i * i;
Diretiva – barrier Sincroniza todos as threads em uma equipe; Todas as threads pausam na barreira, até que todas as threads executem a barreira.
Exemplo – Diretivas master e barrier // Print intermediate results in a single thread. #pragma omp master for (i = 0; i < 5; i++) printf_s("a[%d] = %dn", i, a[i]); // Wait. #pragma omp barrier // Continue with the computation. #pragma omp for (i = 0; i < 5; i++) a[i] += i; } }
Diretiva Schedule
#define THREADS 8 #define N 100 By default, Open. MP statically assigns loop iterations to threads. int main ( ) { int i; #pragma omp parallel for num_threads(THREADS) for (i = 0; i < N; i++) { printf( "Thread %d is doing iteration %d. n", omp_get_thread_num(), i ); } /* all threads done */ printf("All done!n"); return 0; }
#define THREADS 4 A static schedule can be nonoptimal, however. This is the case when the different iterations take different amounts of time. #define N 16 int main ( ) { int i; #pragma omp parallel for schedule(static) num_threads(THREADS) for (i = 0; i < N; i++) { /* wait for i seconds */ sleep(i); printf( "Thread %d has completed iteration %d. n", omp_get_thread_num( ), i); } /* all threads done */ printf("All done!n"); return 0; } This program also specifies static scheduling, in the parallel for directive. This program can be greatly improved with a dynamic schedule.
#define THREADS 4 #define N 16 int main ( ) { int i; #pragma omp parallel for schedule(dynamic) num_threads(THREADS) How much faster does this program run? for (i = 0; i < N; i++) { /* wait for i seconds */ sleep(i); printf( "Thread %d has completed iteration %d. n", omp_get_thread_num( ), i ); } /* all threads done */ printf("All done!n"); return 0; } How much faster does this program run?
Dynamic scheduling is better when the iterations may take very different amounts of time. Dynamic Schedule Overhead However, there is some overhead to dynamic scheduling. After each iteration, the threads must stop and receive a new value of the loop variable to use for its next iteration.
#define THREADS 16 #define N 10000 int main ( ) { The following program demonstrates this overhead: int i; printf( "Running %d iterations on %d threads dynamically. n", N, THREADS); #pragma omp parallel for schedule(dynamic) num_threads(THREADS) for (i = 0; i < N; i++) { /* a loop that doesn't take very long */ } /* all threads done */ printf("All done!n"); return 0; } How long does this program take to execute?
If we specify static scheduling, the program will run faster: #define THREADS 16 #define N 10000 int main ( ) { int i; printf( "Running %d iterations on %d threads statically. n", N, THREADS); #pragma omp parallel for schedule(static) num_threads(THREADS) for (i = 0; i < N; i++) { /* a loop that doesn't take very long */ } /* all threads done */ printf("All done!n"); return 0; }
We can split the difference between static and dynamic scheduling by using chunks in a dynamic schedule. Chunk Sizes Here, each thread will take a set number of iterations, called a “chunk”, execute it, and then be assigned a new chunk when it is done.
By specifying a chunk size of 100 in the program below, we markedly improve the performance: #define THREADS 16 #define N 10000 #define CHUNK 100 int main ( ) { int i; printf("Running %d iterations on %d threads dynamically. n", N, THREADS); #pragma omp parallel for schedule(dynamic, CHUNK) num_threads(THREADS) for (i = 0; i < N; i++) { /* a loop that doesn't take very long */ } /* all threads done */ printf("All done!n"); return 0; }
Increasing or decreasing the chunk size. . . Increasing the chunk size makes the scheduling more static, and decreasing it makes it more dynamic.
Instead of static, or dynamic, we can specify guided as the schedule. Guided Schedules This scheduling policy is similar to a dynamic schedule, except that the chunk size changes as the program runs. It begins with big chunks, but then adjusts to smaller chunk sizes if the workload is imbalanced.
Guided Schedules How does the program above perform with a guided schedule?
Guided Schedules #define THREADS 16 #define N 10000 int main ( ) { int i; printf("Running %d iterations on %d threads guided. n", N, THREADS); #pragma omp parallel for schedule(guided) num_threads(THREADS) for (i = 0; i < N; i++) { /* a loop that doesn't take very long */ } /* all threads done */ printf("All done!n"); return 0; }
How does our program with iterations that take different amounts of time perform with guided scheduling? #define THREADS 4 #define N 16 int main ( ) { int i; #pragma omp parallel for schedule(guided) num_threads(THREADS) for (i = 0; i < N; i++) { /* wait for i seconds */ sleep(i); printf("Thread %d has completed iteration %d. n", omp_get_thread_num( ), i); } /* all threads done */ printf("All done!n"); return 0; }
Open. MP for automatically splits for loop iterations for us. Conclusion But, depending on our program, the default behavior may not be ideal. For loops where each iteration takes roughly equal time, static schedules work best, as they have little overhead.
For loops where each iteration can take very different amounts of time, dynamic schedules, work best as the work will be split more evenly across threads. Scheduled Conclusion Specifying chunks, or using a guided schedule provide a trade-off (uma alternativa) between the two. Choosing the best schedule depends on understanding your loop.
2 problemas: inicialização + valor final! int soma = 0 ; #pragma omp parallel for schedule(static) private(soma) Pr ivate for (i=0 ; i < 10000 ; i++) soma += a[i]; printf(“Terminado — soma = %d”, soma);
int soma = 0 ; #pragma omp parallel for schedule(static) #pragma omp firstprivate(soma) lastprivate(soma) for (i=0 ; i < 10000 ; i++) soma += a[i]; printf(“Terminado”); Resolveu o problema da inicialização e do fim!
Firstprivate Especifica que cada thread deve ter sua própria instância de uma variável, e que a variável deve ser inicializada com o valor da variável, pois ela existe antes da construção parallel.
Lastprivate Especifica que o contexto delimitador da variável é definida igual à versão particular de qualquer thread que executa a iteração final (construção de loop).
reduction Especifica que uma ou mais variáveis que são particulares a cada thread são o assunto de uma operação de redução no final da região paralela.
usada para operações tipo “all-to-one”: exemplo: op = ’+’ reduction (op : list); cada thread terá uma cópia da(s) variável(is) definidas em ’list’ com a devida inicialização; ela efetuará a soma local com sua cópia; ao sair da seção paralela, as somas locais serão automaticamente adicionadas na variavel global.
#include #define NUM_THREADS 4 void main( ) { int i, tmp, res = 0; #pragma omp parallel for reduction(+: res) private(tmp) for (i=0 ; i< 10000 ; i++) { tmp = Calculo( ); res += tmp ; } printf(“O resultado vale %d´´, res) ; } Obs: os índices de laços sempre são privados.
nowait - Substitui a barreira implícita em uma diretiva. #include <stdio. h> #define SIZE 5 void test( int *a, int *b, int *c, int size ) { int i; #pragma omp parallel { #pragma omp for nowait for (i = 0; i < size; i++) b[i] = a[i] * a[i]; #pragma omp for nowait for (i = 0; i < size; i++) c[i] = a[i]/2; } } Se houver vários loops independentes dentro de uma região paralela, você pode usar o nowait para evitar a barreira implícita no final do for, da seguinte maneira: . .
Parallel sections #pragma omp [parallel] sections [clauses] { #pragma omp section { code_block } }
Pode-se usar omp section quando não se usam laços: OMP SECTIONS #pragma omp parallel #pragma omp sections { Calculo 1( ); #pragma omp section Calculo 2( ); #pragma omp section Calculo 3( ); } As seções são distribuídas entre as diferentes threads. Cada seção tem uma lógica diferente (threads diferentes).
- Omp parallel for collapse
- Pedagogia diretiva
- Omp barrier
- Omp atomic capture
- Tendência liberal renovada progressivista slide
- Pragma exception_init
- Vita benko
- Vcl.h
- Udruga pragma
- Paralele
- "pragma"
- Udruga pragma
- Kviz glagoli
- Eros ludus storge pragma mania agape
- Postgresql pragma autonomous_transaction
- Independent dependent clause
- Adjective from t
- Adverb clause reduction
- Non parallel sentence
- What's a parallel sentence
- Parallel sentence
- Parallel force system
- Mary likes hiking swimming and to ride a bicycle
- Parts of fingerprint
- Siso truth table
- Xaveriuscollege
- Cum clause latin
- However in the beginning of a sentence examples
- Spanish adverbial clauses
- Future less vivid latin
- Short story with relative clauses
- Definition of adverbial clause
- Identify the essential
- Adverb clauses are used to express
- Reduced adverb clause passive
- Adjective
- Phrase group
- Noun clause examples
- Coordination in grammar
- Sentence with two independent clauses