programaÇÃo paralela e vetorial avanÇada
TRANSCRIPT
![Page 2: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/2.jpg)
APRESENTAÇÃO
Matheus S. Serpa
https://www.linkedin.com/in/matheusserpa/
Formação:
Graduação em Ciência da Computação (UNIPAMPA 2015)
Mestrado em Computação (UFRGS 2018)
Período sanduíche na Université de Neuchâtel - Suiça
Doutorado em andamento em Computação (UFRGS)
Atividades:
Instrutor de Ciência de Dados na TargetTrust (TT)
Professor na Faculdade São Francisco de Assis (UNIFIN)
100
![Page 3: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/3.jpg)
GRUPO DE PROCESSAMENTO PARALELO E DISTRIBUÍDO
Philippe O. A. Navaux (Coordenador)
Big Data Computer Architecture Fog and Edge Computing
Cloud Computing Machine Learning Oil and Gas
101
![Page 4: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/4.jpg)
MATERIAL DO MINICURSO
Slides
http://www.cenapad-rj.lncc.br/tutoriais/materiais-hpc/semana-sdumont/
Exercicios no Google Colab
https://colab.research.google.com/drive/1ox-Rxl9ueVHvtrRF7f2FFKvqoP0YW8HB
102
![Page 5: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/5.jpg)
APRESENTAÇÃO DA ÁREA
103
![Page 6: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/6.jpg)
POR QUE ESTUDAR PROGRAMAÇÃOPARALELA?
Os programas já não são rápidos o suficiente?
As máquinas já não são rápidas o suficiente?
104
![Page 7: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/7.jpg)
REQUISITOS SEMPRE MUDANDO
105
![Page 8: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/8.jpg)
EVOLUÇÃO DA INTEL E AMD
Onde
comprar um
processador
single-core?
106
![Page 9: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/9.jpg)
EVOLUÇÃO DA INTEL E AMD
107
![Page 10: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/10.jpg)
POR QUE PROGRAMAÇÃO PARALELA?
Dois dos principais motivos para utilizar programação paralela são: Reduzir o tempo necessário para solucionar um problema.
Resolver problemas mais complexos e de maior dimensão.
108
![Page 11: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/11.jpg)
POR QUE PROGRAMAÇÃO PARALELA?
Dois dos principais motivos para utilizar programação paralela são: Reduzir o tempo necessário para solucionar um problema.
Resolver problemas mais complexos e de maior dimensão.
Outros motivos são: Utilizar recursos computacionais subaproveitados.
Ultrapassar limitações de memória quando a memória disponível num único computador é insuficiente para a resolução do problema.
Ultrapassar os limites físicos que atualmente começam a restringir a possibilidade de construção de computadores sequenciais cada vez mais rápidos.
109
![Page 12: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/12.jpg)
OPÇÕES PARA CIENTISTAS DA COMPUTAÇÃO
1. Crie uma nova linguagem para programas paralelos
2. Crie um hardware para extrair paralelismo
3. Deixe o compilador fazer o trabalho sujo
Paralelização automática
Ou crie anotações no código sequencial
4. Use os recursos do sistema operacional
Com memória compartilhada – threads
Com memória distribuída – SPMD
5. Use a estrutura dos dados para definir o paralelismo
6. Crie uma abstração de alto nível – Objetos, funções aplicáveis, etc.
110
![Page 13: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/13.jpg)
PRINCIPAIS MODELOS DE PROGRAMAÇÃO PARALELA
Programação em Memória Compartilhada (OpenMP, CUDA, OpenACC, OpenCL)
Programação usando processos ou threads.
Decomposição do domínio ou funcional com granularidade fina, média ou grossa.
Comunicação através de memória compartilhada.
Sincronização através de mecanismos de exclusão mútua.
Programação em Memória Distribuída (MPI)
Programação usando processos distribuídos
Decomposição do domínio com granularidade grossa.
Comunicação e sincronização por troca de mensagens.
111
![Page 14: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/14.jpg)
FATORES DE LIMITAÇÃO DO DESEMPENHO
Código Sequencial: existem partes do código que são inerentemente sequenciais (e.g. iniciar/terminar a computação).
Concorrência/Paralelismo: o número de tarefas pode ser escasso e/ou de difícil definição.
Comunicação: existe sempre um custo associado à troca de informação e enquanto as tarefas processam essa informação não contribuem para a computação.
Sincronização: a partilha de dados entre as várias tarefas pode levar a problemas de contenção no acesso à memória e enquanto as tarefas ficam à espera de sincronizar não contribuem para a computação.
Granularidade: o número e o tamanho das tarefas é importante porque o tempo que demoram a ser executadas tem de compensar os custos da execução em paralelo (e.g. custos de criação, comunicação e sincronização).
Balanceamento de Carga: ter os processadores maioritariamente ocupados durante toda a execução é decisivo para o desempenho global do sistema.
112
![Page 15: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/15.jpg)
COMO IREMOS PARALELIZAR? PENSANDO!
113
Trabalho
Dados
![Page 16: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/16.jpg)
COMO IREMOS PARALELIZAR? PENSANDO!
114
Dados
![Page 17: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/17.jpg)
COMO IREMOS PARALELIZAR? PENSANDO!
115
Dados
Trabalho
Extra
![Page 18: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/18.jpg)
COMO IREMOS PARALELIZAR? PENSANDO!
116
Divisão e Organização lógica do nosso algoritmo paralelo
![Page 19: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/19.jpg)
UM PROGRAMA DE MEMÓRIA COMPARTILHADA
Uma instância do programa:
Um processo e muitas threads.
Threads interagem através de leituras/escrita com o espaço de endereçamento compartilhado.
Sincronização garante a ordem correta dos resultados.
117
Espaço de
endereçamento
compartilhado
Thread
privado Thread
privado
Thread
privado
Thread
privado
![Page 20: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/20.jpg)
BIBLIOGRAFIABÁSICA
Using OpenMP - Portable
Shared Memory Parallel
Programming
Autores: Barbara Chapman,
Gabriele Jost and Ruud van der
Pas
Editora: MIT Press
Ano: 2007
118
![Page 21: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/21.jpg)
LEI DE AMDAHL(1967)
119
![Page 22: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/22.jpg)
LEI DE AMDAHL
Tempo de execução em um único processador:
Parte
sequencial
Parte
paralelizável
Parte
sequencial
𝑇(1)
1 − 𝛽
𝛽 = fração de código que é puramente sequencial
120
![Page 23: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/23.jpg)
LEI DE AMDAHL
Parte sequencial Parte paralelizável Parte seq.
𝑇 1
1 − 𝛽
Tempo de
execução em um
único processador
Parte
sequencial
Parte
paralelizável
Parte
sequencial
𝑇 2 = 𝑇 1 × 𝛽 + 1 − 𝛽 ×𝑇 1
2
(1 − 𝛽) ×𝑇 1
2
Tempo de
execução em 2
processadores
121
![Page 24: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/24.jpg)
LEI DE AMDAHL
Seja 0 ≤ 𝛽 ≤ 1 a fração da computação que só pode ser realizada sequencialmente.
A lei de Amdahl diz-nos que o speedup máximo que uma aplicação paralela com 𝑝 processadores pode obter é:
𝑆 𝑝 =1
𝛽 +1 − 𝛽𝑝
A lei de Amdahl também pode ser utilizada para determinar o limite máximo de speedup que uma determinada aplicação poderá alcançar independentemente do número de processadores a utilizar (limite máximo teórico).
122
![Page 25: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/25.jpg)
INTRODUÇÃO AO OPENMP
123
![Page 26: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/26.jpg)
INTRODUÇÃO
OpenMP é um dos modelos de programação paralelas mais usados hoje em dia.
Esse modelo é relativamente fácil de usar, o que o torna um bom modelo para iniciar o aprendizado sobre escrita de programas paralelos.
Observações:
Assumo que todos sabem programar em linguagem C. OpenMP também suporta Fortran e C++, mas vamos nos restringir a C.
124
![Page 27: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/27.jpg)
SINTAXE BÁSICA - OPENMPTipos e protótipos de funções no arquivo:
#include <omp.h>
A maioria das construções OpenMP são diretivas de compilação.
#pragma omp construct [clause [clause]...] Exemplo:
#pragma omp parallel private(var1, var2) shared(var3, var4)
A maioria das construções se aplicam a um bloco estruturado.
Bloco estruturado: Um bloco com um ou mais declarações com um ponto de entrada no topo e um ponto de saída no final.
Podemos ter um exit() dentro de um bloco desses.125
![Page 28: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/28.jpg)
NOTAS DE COMPILAÇÃO
Linux e OS X com gcc:
gcc -fopenmp foo.c #GCC
export OMP_NUM_THREADS=40
./a.out
126
Para shell bash
Mas vamos
usar Linux
☺
Também
funciona no
Windows!
Até mesmo
no Visual
Studio!
Por padrão é o nº de
proc. virtuais.
![Page 29: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/29.jpg)
FUNÇÕES
Funções da biblioteca OpenMP.
127
// Arquivo interface da biblioteca OpenMP para C/C++#include <omp.h>
// retorna o identificador da thread.int omp_get_thread_num();
// indica o número de threads a executar na região paralela.void omp_set_num_threads(int num_threads);
// retorna o número de threads que estão executando no momento.int omp_get_num_threads();
// Comando para compilação habilitando o OpenMP.gcc –o hello hello.c –fopenmp
![Page 30: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/30.jpg)
DIRETIVAS
Diretivas do OpenMP.
128
// Cria a região paralela. Define variáveis privadas e compartilhadas entre as threads.#pragma omp parallel private(...) shared(...){ // Obrigatoriamente na linha de baixo.
// Apenas a thread mais rápida executa.#pragma omp single
}
![Page 31: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/31.jpg)
cd 1-helloWorld/ sbatch exec.batch cat XX.out
EXERCÍCIO 1: HELLO WORLD
129
#include <stdio.h>
int main(){int myid, nthreads;
myid = 0;
nthreads = 1;printf("%d of %d – hello world!\n", myid, nthreads);
return 0;}
0 of 1 – hello world!
![Page 32: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/32.jpg)
SOLUÇÃO 1.1: HELLO WORLD
Variáveis privadas.
130
#include <stdio.h>#include <omp.h>int main(){int myid, nthreads;
#pragma omp parallel private(myid, nthreads){myid = omp_get_thread_num();
nthreads = omp_get_num_threads();printf("%d of %d – hello world!\n", myid, nthreads);}return 0;
}
0 of 2 – hello world!
1 of 2 – hello world!
cd 1-helloWorld/ sbatch exec.batch cat XX.out
![Page 33: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/33.jpg)
SOLUÇÃO 1.2: HELLO WORLD
Variáveis privadas e compartilhadas.
131
#include <stdio.h>#include <omp.h>int main(){int myid, nthreads;
#pragma omp parallel private(myid) shared(nthreads){myid = omp_get_thread_num();#pragma omp singlenthreads = omp_get_num_threads();printf("%d of %d – hello world!\n", myid, nthreads);}return 0;
}
0 of 2 – hello world!
1 of 2 – hello world!
cd 1-helloWorld/ sbatch exec.batch cat XX.out
![Page 34: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/34.jpg)
SOLUÇÃO 1.3: HELLO WORLD
NUM_THREADS fora da região paralela.
132
#include <stdio.h>#include <omp.h>int main(){int myid, nthreads;
nthreads = omp_get_num_threads();#pragma omp parallel private(myid) shared(nthreads){myid = omp_get_thread_num();printf("%d of %d – hello world!\n", myid, nthreads);}return 0;
}
cd 1-helloWorld/ sbatch exec.batch cat XX.out
![Page 35: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/35.jpg)
SOLUÇÃO 1.3: HELLO WORLD
NUM_THREADS fora da região paralela.
Não funciona.
133
#include <stdio.h>#include <omp.h>int main(){int myid, nthreads;
nthreads = omp_get_num_threads();#pragma omp parallel private(myid) shared(nthreads){myid = omp_get_thread_num();printf("%d of %d – hello world!\n", myid, nthreads);}return 0;
}
0 of 1 – hello world!
1 of 1 – hello world!
![Page 36: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/36.jpg)
DISTRIBUIÇÃO CÍCLICA DE ITERAÇÕES DO LAÇO
T0 T1 T2 T3 T0 T1 T2 T3 ...
134
// Laço originalfor(i = 0; i < N; i++)
// Distribuição cíclicafor(i = myid; i < N; i += nthreads)
![Page 37: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/37.jpg)
cd 2-vectorSum/ sbatch exec.batch cat XX.out
EXERCÍCIO 2, PARTE A: VECTOR SUM
135
long long int sum(int *v, long long int N){long long int i, sum = 0;
for(i = 0; i < N; i++)sum += v[i];
return sum
}
![Page 38: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/38.jpg)
FUNÇÕES
Funções da biblioteca OpenMP.
136
// Arquivo interface da biblioteca OpenMP para C/C++#include <omp.h>
// retorna o identificador da thread.int omp_get_thread_num();
// indica o número de threads a executar na região paralela.void omp_set_num_threads(int num_threads);
// retorna o número de threads que estão executando no momento.int omp_get_num_threads();
// Comando para compilação habilitando o OpenMP.gcc –o hello hello.c –fopenmp
![Page 39: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/39.jpg)
DIRETIVAS
Diretivas do OpenMP.
137
// Cria a região paralela. Define variáveis privadas e compartilhadas entre as threads.#pragma omp parallel private(...) shared(...){ // Obrigatoriamente na linha de baixo.
// Apenas a thread mais rápida executa.#pragma omp single
}
![Page 40: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/40.jpg)
SOLUÇÃO 2.1, PARTE B: VECTOR SUM
138
sum = 0;#pragma omp parallel private(i, myid)
{myid = omp_get_thread_num();#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)
sum += v[i];} ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 41: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/41.jpg)
SOLUÇÃO 2.1, PARTE B: VECTOR SUM
139
sum = 0;#pragma omp parallel private(i, myid)
{myid = omp_get_thread_num();#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)
sum += v[i];} ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 42: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/42.jpg)
SOLUÇÃO 2.1, PARTE B: VECTOR SUM
140
sum = 0;#pragma omp parallel private(i, myid)
{myid = omp_get_thread_num();#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)// RACE CONDITIONsum += v[i]; // ler sum, v[i]; somar; escrever sum;
} ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 43: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/43.jpg)
COMO AS THREADS INTERAGEM?
OpenMP é um modelo de multithreading de memória compartilhada. Threads se comunicam através de variáveis compartilhadas.
Compartilhamento não intencional de dados causa condições de corrida. Condições de corrida: quando a saída do programa muda quando a threads são
escalonadas de forma diferente.
Apesar de este ser um aspectos mais poderosos da utilização de threads, também pode ser um dos mais problemáticos.
O problema existe quando dois ou mais threads tentam acessar/alterar as mesmas estruturas de dados (condições de corrida).
Para controlar condições de corrida: Usar sincronização para proteger os conflitos por dados
Sincronização é cara, por isso: Tentaremos mudar a forma de acesso aos dados para minimizar a necessidade de
sincronizações.
141
![Page 44: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/44.jpg)
CONDIÇÕES DE CORRIDA: EXEMPLO
Thread 0 Thread 1 sum
0
Leia sum
0
0
Leia sum
0
0
Some 0, 5
5
0
Some 0, 10
10
0
Escreva 5, sum
5
5
Escreva 10, sum
10
10
142
15 !?
TEM
PO
![Page 45: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/45.jpg)
CONDIÇÕES DE CORRIDA: EXEMPLO
Thread 0 Thread 1 sum
0
Leia sum
0
0
Leia sum
0
0
Some 0, 5
5
0
Some 0, 10
10
0
Escreva 5, sum
5
5
Escreva 10, sum
10
10
143
15 !?
TEM
PO
Devemos garantir que não importa a ordem de
execução (escalonamento), teremos sempre um
resultado consistente!
![Page 46: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/46.jpg)
SINCRONIZAÇÃO
Assegura que uma ou mais threads estão em um estado bem definido em um ponto conhecido da execução.
As duas formas mais comuns de sincronização são:
144
![Page 47: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/47.jpg)
SINCRONIZAÇÃO
Assegura que uma ou mais threads estão em um estado bem definido em um ponto conhecido da execução.
As duas formas mais comuns de sincronização são:
Barreira: Cada thread espera na barreiraaté a chegada de todas as demais
145
![Page 48: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/48.jpg)
SINCRONIZAÇÃO
Assegura que uma ou mais threads estão em um estado bem definido em um ponto conhecido da execução.
As duas formas mais comuns de sincronização são:
Barreira: Cada thread espera na barreiraaté a chegada de todas as demais
Exclusão mútua: Define um bloco de códigoonde apenas uma thread pode executar por vez.
146
![Page 49: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/49.jpg)
SINCRONIZAÇÃO: BARRIER
Barrier: Cada thread espera até que as demais cheguem.
147
#pragma omp parallel{
int id = omp_get_thread_num(); // variável privadaA[id] = big_calc1(id);
#pragma omp barrier
B[id] = big_calc2(id, A); } // Barreira implícita
![Page 50: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/50.jpg)
SINCRONIZAÇÃO: CRITICAL
Exclusão mútua: Apenas uma thread pode entrar por vez
INTEL MODERN CODE PARTNER 148
#pragma omp parallel{
float B; // variável privadaint i, myid, nthreads; // variáveis privadamyid = omp_get_thread_num();nthreads = omp_get_num_threads();for(i = myid; i < niters; i += nthreads){B = big_job(i); // Se for pequeno, muito overhead#pragma omp criticalres += consume (B);
}}
As threads esperam sua vez,
apenas uma chama consume()
por vez.
![Page 51: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/51.jpg)
SINCRONIZAÇÃO: ATOMIC
atomic prove exclusão mútua para operações específicas.
149
#pragma omp parallel{
double tmp, B;B = DOIT();tmp = big_ugly(B);#pragma omp atomicX += tmp;
}
Algumas operações aceitáveis:
v = x;x = expr;
x++; ++x; x--; --x;x op= expr;
v = x op expr;v = x++; v = x--; v = ++x; v = --x;
Instruções especiais da
arquitetura (se
disponível)
![Page 52: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/52.jpg)
EXERCÍCIO 2, PARTE C: VECTOR SUM
150
sum = 0;#pragma omp parallel private(i, myid)
{myid = omp_get_thread_num();#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)
sum += v[i]; } ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 53: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/53.jpg)
SOLUÇÃO 2.2, PARTE C: VECTOR SUM
151
sum = 0;#pragma omp parallel private(i, myid)
{myid = omp_get_thread_num();#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)#pragma omp criticalsum += v[i];
} ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 54: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/54.jpg)
SOLUÇÃO 2.3, PARTE C: VECTOR SUM
152
sum = 0;#pragma omp parallel private(i, myid)
{myid = omp_get_thread_num();#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)#pragma omp atomicsum += v[i];
} ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 55: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/55.jpg)
EXERCÍCIO 2, PARTE D: VECTOR SUM
153
sum = 0;#pragma omp parallel private(i, myid)
{myid = omp_get_thread_num();#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)#pragma omp atomicsum += v[i];
} ...
Qual o problema da seção crítica dentro do loop?
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 56: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/56.jpg)
EXERCÍCIO 2, PARTE D: VECTOR SUM
154
sum = 0;#pragma omp parallel private(i, myid)
{myid = omp_get_thread_num();#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)#pragma omp atomicsum += v[i];
} ... Regiões atomic – n vezes. Ex. 1 000 000 000
Qual o problema da seção crítica dentro do loop?
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 57: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/57.jpg)
SOLUÇÃO 2.4, PARTE D: VECTOR SUM
155
sum = 0;#pragma omp parallel private(i, sum_local, myid)
{myid = omp_get_thread_num(); sum_local = 0;#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 58: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/58.jpg)
SOLUÇÃO 2.4, PARTE D: VECTOR SUM
156
sum = 0;#pragma omp parallel private(i, sum_local, myid)
{myid = omp_get_thread_num(); sum_local = 0;#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ... Regiões atomic – nthreads vezes. Ex. 40 threads / vezes
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 59: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/59.jpg)
EXERCÍCIO 2, PARTE E: VECTOR SUM
157
sum = 0;#pragma omp parallel private(i, sum_local, myid)
{myid = omp_get_thread_num(); sum_local = 0;#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ...
Existe uma solução melhor?
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 60: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/60.jpg)
EXERCÍCIO 2, PARTE E: VECTOR SUM
158
sum = 0;#pragma omp parallel private(i, sum_local, myid)
{myid = omp_get_thread_num(); sum_local = 0;#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ...
Existe uma solução melhor?
Como a cache funciona?
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 61: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/61.jpg)
PRINCÍPIO DA LOCALIDADE
Programas repetem trechos de código e acessam repetidamente dados próximos.
Localidade Temporal: posições de memória, uma vez acessadas, tendem a ser acessadas novamente em um espaço curto de tempo.
Localidade Espacial: se um item é referenciado, itens cujos endereços sejam próximos dele tendem a ser referenciados em um espaço curto de tempo.
159
![Page 62: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/62.jpg)
ACESSOS INTERCALADOS
160
Cache 0 – Thread 0 Cache 1 – Thread 1 Cache 2 – Thread 2 Cache 3 – Thread 3
v[0] v[1] v[2] v[3] v[0] v[1] v[2] v[3] v[0] v[1] v[2] v[3] v[0] v[1] v[2] v[3]
Cache 0 – Thread 0 Cache 1 – Thread 1 Cache 2 – Thread 2 Cache 3 – Thread 3
v[4] v[5] v[6] v[7] v[4] v[5] v[6] v[7] v[4] v[5] v[6] v[7] v[4] v[5] v[6] v[7]
Cache 0 – Thread 0 Cache 1 – Thread 1 Cache 2 – Thread 2 Cache 3 – Thread 3
v[8] v[9] v[10] v[11] v[8] v[9] v[10] v[11] v[8] v[9] v[10] v[11] v[8] v[9] v[10] v[11]
Cache 0 – Thread 0 Cache 1 – Thread 1 Cache 2 – Thread 2 Cache 3 – Thread 3
v[12] v[13] v[14] v[15] v[12] v[13] v[14] v[15] v[12] v[13] v[14] v[15] v[12] v[13] v[14] v[15]
TEM
PO
for(i = myid; i < N; i += nthreads)
25% do conteúdo trazido para a cache é utilizado.
![Page 63: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/63.jpg)
ACESSOS CONSECUTIVOS
161
Cache 0 – Thread 0 Cache 1 – Thread 1 Cache 2 – Thread 2 Cache 3 – Thread 3
v[0] v[1] v[2] v[3] v[4] v[5] v[6] v[7] v[8] v[9] v[10] v[11] v[12] v[13] v[14] v[15]
Cache 0 – Thread 0 Cache 1 – Thread 1 Cache 2 – Thread 2 Cache 3 – Thread 3
v[0] v[1] v[2] v[3] v[4] v[5] v[6] v[7] v[8] v[9] v[10] v[11] v[12] v[13] v[14] v[15]
Cache 0 – Thread 0 Cache 1 – Thread 1 Cache 2 – Thread 2 Cache 3 – Thread 3
v[0] v[1] v[2] v[3] v[4] v[5] v[6] v[7] v[8] v[9] v[10] v[11] v[12] v[13] v[14] v[15]
Cache 0 – Thread 0 Cache 1 – Thread 1 Cache 2 – Thread 2 Cache 3 – Thread 3
v[0] v[1] v[2] v[3] v[4] v[5] v[6] v[7] v[8] v[9] v[10] v[11] v[12] v[13] v[14] v[15]
TEM
PO
for(i = ini; i < end; i++)
100% do conteúdo trazido para a cache é utilizado.
![Page 64: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/64.jpg)
EXERCÍCIO 2, PARTE E: VECTOR SUM
162
sum = 0;#pragma omp parallel private(i, sum_local, myid){myid = omp_get_thread_num(); sum_local = 0;#pragma omp single{nthreads = omp_get_num_threads();}
for(i = myid; i < N; i += nthreads)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 65: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/65.jpg)
SOLUÇÃO 2.5, PARTE E: VECTOR SUM
163
sum = 0;#pragma omp parallel private(i, sum_local, myid, init, end){myid = omp_get_thread_num(); sum_local = 0;#pragma omp single{nthreads = omp_get_num_threads(); slice = N / nthreads;}init = myid * slice;if(myid == nthreads – 1) end = N; else end = init + slice;for(i = init; i < end; i++)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 66: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/66.jpg)
EXERCÍCIO 2, PARTE F: VECTOR SUM
164
sum = 0;#pragma omp parallel private(i, sum_local, myid, init, end){myid = omp_get_thread_num(); sum_local = 0;#pragma omp single{nthreads = omp_get_num_threads(); slice = N / nthreads;}init = myid * slice;if(myid == nthreads – 1) end = N; else end = init + slice;for(i = init; i < end; i++)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ... OpenMP é um modelo relativamente fácil de usar
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 67: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/67.jpg)
CONSTRUÇÕES DE DIVISÃO DE LAÇOS
A construção de divisão de trabalho em laços divide as iterações do laço entre as threads do time.
165
#pragma omp parallel private(i) shared(N){#pragma omp forfor(i = 0; i < N; i++)
NEAT_STUFF(i);}
A variável i será feita privada para cada thread por
padrão. Você poderia fazer isso explicitamente com a
cláusula private(i)
![Page 68: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/68.jpg)
CONSTRUÇÕES DE DIVISÃO DE LAÇOSUM EXEMPLO MOTIVADOR
Código sequencial
166
for(i = 0; i < N; i++)a[i] = a[i] + b[i];
![Page 69: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/69.jpg)
CONSTRUÇÕES DE DIVISÃO DE LAÇOSUM EXEMPLO MOTIVADOR
Código sequencial
Região OpenMP parallel
167
for(i = 0; i < N; i++)a[i] = a[i] + b[i];
#pragma omp parallel{int id, i, Nthrds, istart, iend;id = omp_get_thread_num();Nthrds = omp_get_num_threads();istart = id * N / Nthrds;iend = (id+1) * N / Nthrds;if(id == Nthrds-1) iend = N;for(i = istart; i < iend; i++)a[i] = a[i] + b[i];
}
![Page 70: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/70.jpg)
CONSTRUÇÕES DE DIVISÃO DE LAÇOSUM EXEMPLO MOTIVADOR
Código sequencial
Região OpenMP parallel
Região paralela OpenMPcom uma construção dedivisão de laço
INTEL MODERN CODE PARTNER 168
#pragma omp parallel#pragma omp forfor(i = 0; i < N; i++) a[i] = a[i] + b[i];
for(i = 0; i < N; i++)a[i] = a[i] + b[i];
#pragma omp parallel{int id, i, Nthrds, istart, iend;id = omp_get_thread_num();Nthrds = omp_get_num_threads();istart = id * N / Nthrds;iend = (id+1) * N / Nthrds;if(id == Nthrds-1) iend = N;for(i = istart; i < iend; i++)a[i] = a[i] + b[i];
}
![Page 71: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/71.jpg)
CONSTRUÇÕES PARALELA E DIVISÃO DE LAÇOS COMBINADAS
Algumas cláusulas podem ser combinadas.
169
double res[MAX]; int i;#pragma omp parallel{#pragma omp forfor(i=0; i < MAX; i++)res[i] = huge();
}
double res[MAX]; int i;#pragma omp parallel forfor(i=0; i < MAX; i++)res[i] = huge();
![Page 72: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/72.jpg)
EXERCÍCIO 2, PARTE F: VECTOR SUM
170
sum = 0;#pragma omp parallel private(i, sum_local, myid, init, end){myid = omp_get_thread_num(); sum_local = 0;#pragma omp single{nthreads = omp_get_num_threads(); slice = N / nthreads;}init = myid * slice;if(myid == nthreads – 1) end = N; else end = init + slice;for(i = init; i < end; i++)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 73: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/73.jpg)
SOLUÇÃO 2.6, PARTE F: VECTOR SUM
171
sum = 0;#pragma omp parallel private(i, sum_local){
sum_local = 0;
#pragma omp forfor(i = 0; i < N; i++)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 74: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/74.jpg)
EXERCÍCIO 2, PARTE G: VECTOR SUM
172
sum = 0;#pragma omp parallel private(i, sum_local){
sum_local = 0;
#pragma omp forfor(i = 0; i < N; i++)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ... OpenMP é um modelo relativamente fácil de usar
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 75: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/75.jpg)
REDUÇÃO
Combinação de variáveis locais de uma thread em uma variável única. Essa situação é bem comum, e chama-se redução.
O suporte a tal operação é fornecido pela maioria dos ambientes de programação paralela.
173
![Page 76: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/76.jpg)
DIRETIVA REDUCTION
reduction(op : list_vars)
Dentro de uma região paralela ou de divisão de trabalho: Será feita uma cópia local de cada variável na lista
Será inicializada dependendo da op (ex. 0 para +, 1 para *).
Atualizações acontecem na cópia local.
Cópias locais são “reduzidas” para uma única variável original (global).
#pragma omp for reduction(* : var_mult)
174
![Page 77: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/77.jpg)
EXERCÍCIO 2, PARTE G: VECTOR SUM
175
sum = 0;#pragma omp parallel private(i, sum_local){
sum_local = 0;
#pragma omp forfor(i = 0; i < N; i++)sum_local += v[i];
#pragma omp atomicsum += sum_local;} ... OpenMP é um modelo relativamente fácil de usar
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 78: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/78.jpg)
SOLUÇÃO 2.7, PARTE G: VECTOR SUM
176
sum = 0;
#pragma omp parallel for private(i) reduction(+ : sum)for(i = 0; i < N; i++)sum += v[i];
...
cd 2-vectorSum/ sbatch exec.batch cat XX.out
![Page 79: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/79.jpg)
Sequencial vs. Paralelo
VECTOR SUM
177
sum = 0;
for(i = 0; i < N; i++)sum += v[i];
sum = 0;#pragma omp parallel for reduction(+ : sum)for(i = 0; i < N; i++)sum += v[i];
![Page 80: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/80.jpg)
cd 3-selectionSort/ sbatch exec.batch cat XX.out
EXERCÍCIO 3: SELECTION SORT
178
void selection_sort(int *v, int n){int i, j, min, tmp;
for(i = 0; i < n - 1; i++){min = i;
for(j = i + 1; j < n; j++)if(v[j] < v[min])min = j;
tmp = v[i];v[i] = v[min];v[min] = tmp;
}}
![Page 81: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/81.jpg)
SOLUÇÃO 3.1: SELECTION SORT
179
for(i = 0; i < n - 1; i++){#pragma omp parallel default(shared) private(j, min_local){ min_local = i;#pragma omp single min = i#pragma omp forfor(j = i + 1; j < n; j++) if(v[j] < v[min_local])
min_local = j;#pragma omp criticalif(v[min_local] < v[min]) min = min_local;}
tmp = v[i];v[i] = v[the_min];v[the_min] = tmp;
}
cd 3-selectionSort/ sbatch exec.batch cat XX.out
![Page 82: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/82.jpg)
CONSTRUÇÕES DE DIVISÃO DE LAÇOS :A DECLARAÇÃO SCHEDULE
A declaração schedule afeta como as iterações do laço serão mapeadas entre as threads
180
Como o laço
será mapeado
para as
threads?
![Page 83: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/83.jpg)
CONSTRUÇÕES DE DIVISÃO DE LAÇOS :A DECLARAÇÃO SCHEDULE
schedule(static [,chunk])
Distribui iterações de tamanho “chunk” para cada thread
Se “chunk” é omitido, as iterações tem tamanho aproximadamente igual para cada thread
schedule(dynamic[,chunk])
Inicialmente cada thread recebe um “chunk” de iterações, quando termina este “chunk” a thread
acessa uma fila compartilhada para pegar o próximo “chunk” até que todas as iterações sejam
executadas.
Se “chunk” é omitido, cada pedaço tem tamanho 1
schedule(guided[,chunk])
As threads pegam blocos de iterações dinamicamente, iniciando de blocos grandes reduzindo até
o tamanho “chunk”.
⚫ Variação de dynamic para reduzir o overhead de escalonamento. Inicia com blocos grandes
o que diminui o número de decisões de escalonamento.
181
![Page 84: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/84.jpg)
CONSTRUÇÕES DE DIVISÃO DE LAÇOS :A DECLARAÇÃO SCHEDULE
schedule(runtime)
O modelo de distribuição e o tamanho serão pegos da variável de ambiente OMP_SCHEDULE.
⚫ programador decide na hora da execução.
⚫ Exemplo: OMP_SCHEDULE="guided,2"
schedule(auto)
Deixa a divisão por conta da biblioteca em tempo de execução (pode fazer algo diferente dos
acima citados).
182
![Page 85: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/85.jpg)
CONSTRUÇÕES DE DIVISÃO DE LAÇOS :A DECLARAÇÃO SCHEDULE
183
Como o laço
será mapeado
para as
threads?
Tipo de Schedule Quando usar
STATIC Pré determinado e previsível pelo
programador
DYNAMIC Imprevisível, quantidade de
trabalho por iteração altamente
variável
GUIDED Caso especial do dinâmico para
reduzir o overhead dinâmico
AUTO Quando o tempo de execução
pode “aprender” com as iterações
anteriores do mesmo laço
Menos trabalho durante
a execução (mais
durante a compilação)
Mais trabalho durante
a execução (lógica
complexa de controle)
![Page 86: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/86.jpg)
CONSTRUÇÕES DE DIVISÃO DE LAÇOS :A DECLARAÇÃO SCHEDULE
184
Exemplo de escalonamento para 200 iterações.Fonte: Chapman, B. Using OpenMP : portable shared memory parallel programming
![Page 87: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/87.jpg)
cd 4-schedule/ sbatch exec.batch cat XX.out
EXERCÍCIO 4: VECTOR ID - SCHEDULE
185
void schedule(int *v, long long int N){long long int i;
for(i = 0; i < N; i++){v[i] = 0;sleep(1);
}
}
![Page 88: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/88.jpg)
SOLUÇÃO 4.1: VECTOR ID - SCHEDULE
186
void schedule(int *v, long long int N){long long int i;
#pragma omp parallel for schedule(static, 2)for(i = 0; i < N; i++){
v[i] = omp_get_num_thread();sleep(1);
}
}
cd 4-schedule/ sbatch exec.batch cat XX.out
![Page 89: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/89.jpg)
SOLUÇÃO 4.1: VECTOR ID - SCHEDULE
187
void schedule(int *v, long long int N){long long int i;
#pragma omp parallel for schedule(dynamic, 2)for(i = 0; i < N; i++){
v[i] = omp_get_num_thread();sleep(1);
}
}
cd 4-schedule/ sbatch exec.batch cat XX.out
![Page 90: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/90.jpg)
SOLUÇÃO 4.1: VECTOR ID - SCHEDULE
188
void schedule(int *v, long long int N){long long int i;
#pragma omp parallel for schedule(guided, 2)for(i = 0; i < N; i++){
v[i] = omp_get_num_thread();sleep(1);
}
}
cd 4-schedule/ sbatch exec.batch cat XX.out
![Page 91: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/91.jpg)
cd 5-mandelbroat/ sbatch exec.batch cat XX.out
EXERCÍCIO 5: MANDELBROAT
189
int main(){
...for(i = 0; i < m; i++){...for(j = 0; j < n; j++){...for(k = 1; k <= count_max; k++){
...}...
}...
}}
![Page 92: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/92.jpg)
cd 5-mandelbroat/ sbatch exec.batch cat XX.out
SOLUÇÃO 5: MANDELBROAT
190
int main(){...#pragma omp parallel for schedule(dynamic, 1) private(i, j,
k, x, x1, x2, y, y1, y2, c)for(i = 0; i < m; i++){...for(j = 0; j < n; j++){...for(k = 1; k <= count_max; k++){
...}...
}...
}}
![Page 93: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/93.jpg)
INTRODUÇÃO A PROGRAMAÇÃO VETORIAL
191
![Page 94: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/94.jpg)
SINGLE INTRUCTION MULTIPLE DATA(SIMD)Técnica aplicada por unidade de execução
Opera em mais de um elemento por iteração.
Reduz número de instruções significativamente.
Elementos são armazenados em registradores SIMD
192
for(i = 0; i < N; i++)c[i] = a[i] + b[i];
for(i = 0; i < N; i += 4)c[i:4] = a[i:4] + b[i:4];
a[i:4]
b[i:4]
c[i:4]
Scalar
Uma instrução. Uma operação.
Vector
Uma instrução. Quatro operações, por exemplo.
![Page 95: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/95.jpg)
SINGLE INTRUCTION MULTIPLE DATA(SIMD)Técnica aplicada por unidade de execução
Opera em mais de um elemento por iteração.
Reduz número de instruções significativamente.
Elementos são armazenados em registradores SIMD
193
for(i = 0; i < N; i++)c[i] = a[i] + b[i];
for(i = 0; i < N; i += 4)c[i:4] = a[i:4] + b[i:4];
a[i:4]
b[i:4]
c[i:4]
Scalar
Uma instrução. Uma operação.
Vector
Uma instrução. Quatro operações, por exemplo.
Dados contíguos para desempenho ótimo
c[0] c[1] c[2] c[3] …
![Page 96: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/96.jpg)
PROGRAMAÇÃO VETORIAL
194
#pragma omp simd reduction(+ : v) for(i = 0; i < N; i++)v += a[i] + b[i];
Vetorização com redução
#pragma omp simdfor(i = 0; i < N; i++)c[i] = a[i] + b[i];
Vetorização
![Page 97: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/97.jpg)
cd 6-dotProduct/ sbatch exec.batch cat XX.out
EXERCÍCIO 6, PARTE A: DOT PRODUCT SIMD
195
double dotproduct(double *a, int *b, long long int N){long long int i;double dot = 0.0;
for(i = 0; i < N; i++)dot += a[i] * b[i];
return dot;
}
![Page 98: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/98.jpg)
SOLUÇÃO 6.1, PARTE A: DOT PRODUCT SIMD
196
double dotproduct(double *a, int *b, long long int N){long long int i;double dot = 0.0;
#pragma omp simd reduction(+ : dot)for(i = 0; i < N; i++)dot += a[i] * b[i];
return dot;
}
cd 6-dotProduct/ sbatch exec.batch cat XX.out
![Page 99: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/99.jpg)
EXERCÍCIO 6, PARTE B: DOT PRODUCT PARALLEL SIMD
197
double dotproduct(double *a, int *b, long long int N){long long int i;double dot = 0.0;
for(i = 0; i < N; i++)dot += a[i] * b[i];
return dot;
}
cd 6-dotProduct/ sbatch exec.batch cat XX.out
![Page 100: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/100.jpg)
SOLUÇÃO 6.2, PARTE B: DOT PRODUCT PARALLEL SIMD
198
double dotproduct(double *a, int *b, long long int N){long long int i;double dot = 0.0;
#pragma omp parallel for simd reduction(+ : dot)for(i = 0; i < N; i++)dot += a[i] * b[i];
return dot;
}
cd 6-dotProduct/ sbatch exec.batch cat XX.out
![Page 101: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/101.jpg)
EXERCÍCIO 7, PARTE A: MM - SIMD
199
void matrix_mult(double *A, *B, *C, int N){int i, j, k;
for(i = 0; i < N; i++)for(j = 0; j < N; j++)for(k = 0; k < N; k++)C[i * N + j] += A[i * N + k] * B[k * N + j];
}
cd 7-matrixMultiplication/ sbatch exec.batch cat XX.out
![Page 102: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/102.jpg)
SOLUÇÃO 7.1, PARTE A: MM – SIMD
200
void matrix_mult(double *A, *B, *C, int N){int i, j, k;
for(i = 0; i < N; i++)for(j = 0; j < N; j++)#pragma omp simdfor(k = 0; k < N; k++)C[i * N + j] += A[i * N + k] * B[k * N + j];
}
cd 7-matrixMultiplication/ sbatch exec.batch cat XX.out
![Page 103: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/103.jpg)
SOLUÇÃO 7.1, PARTE A: MM – SIMD WRONG
201
void matrix_mult(double *A, *B, *C, int N){int i, j, k;
for(i = 0; i < N; i++)for(j = 0; j < N; j++)#pragma omp simdfor(k = 0; k < N; k++)C[i * N + j] += A[i * N + k] * B[k * N + j];
}
cd 7-matrixMultiplication/ sbatch exec.batch cat XX.out
![Page 104: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/104.jpg)
EXERCÍCIO 7, PARTE B: MM - SIMD
202
void matrix_mult(double *A, *B, *C, int N){int i, j, k;
for(i = 0; i < N; i++)for(j = 0; j < N; j++)#pragma omp simdfor(k = 0; k < N; k++)C[i * N + j] += A[i * N + k] * B[k * N + j];
}
cd 7-matrixMultiplication/ sbatch exec.batch cat XX.out
![Page 105: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/105.jpg)
SOLUÇÃO 7.2, PARTE B: MM - SIMD
203
void matrix_mult(double *A, *B, *C, int N){int i, j, k;
for(i = 0; i < N; i++)for(k = 0; k < N; k++)#pragma omp simdfor(j = 0; j < N; j++)C[i * N + j] += A[i * N + k] * B[k * N + j];
}
cd 7-matrixMultiplication/ sbatch exec.batch cat XX.out
![Page 106: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/106.jpg)
EXERCÍCIO 7, PARTE C: MM – PARALLEL SIMD
204
void matrix_mult(double *A, *B, *C, int N){int i, j, k;
for(i = 0; i < N; i++)for(k = 0; k < N; k++)#pragma omp simdfor(j = 0; j < N; j++)C[i * N + j] += A[i * N + k] * B[k * N + j];
}
cd 7-matrixMultiplication/ sbatch exec.batch cat XX.out
![Page 107: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/107.jpg)
SOLUÇÃO 7.3, PARTE C: MM – PARALLEL SIMD
205
void matrix_mult(double *A, *B, *C, int N){int i, j, k;
#pragma omp parallel for private(i, j, k)for(i = 0; i < N; i++)for(k = 0; k < N; k++)
#pragma omp simdfor(j = 0; j < N; j++)C[i * N + j] += A[i * N + k] * B[k * N + j];
}
cd 7-matrixMultiplication/ sbatch exec.batch cat XX.out
![Page 108: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/108.jpg)
INSTRUÇÕES AVX
Conjunto de Instruções utilizadas para melhorar o desempenho de operações de ponto flutuante.
IA / Processamento de Imagens / Criptografia / Compressão de dados
https://software.intel.com/sites/landingpage/IntrinsicsGuide/
https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/X86-Built-in-Functions.html
#include <immintrin.h>
Tipos de dados: __int64 __m256d __m256i
Instruções: _mm256_set_pd _mm256_load_pd _mm256_mul_pd _mm256_add_pd _mm256_storeu_pd
206
![Page 109: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/109.jpg)
INSTRUÇÕES AVX
__m256d _mm256_set_pd (double e3, double e2, double e1, double e0)
Description
Set packed double-precision (64-bit) floating-point elements in dst with thesupplied values.
Operation
dst[63:0] := e0dst[127:64] := e1dst[191:128] := e2dst[255:192] := e3dst[MAX:256] := 0
207
![Page 110: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/110.jpg)
INSTRUÇÕES AVX
__m256d _mm256_load_pd (double const * mem_addr)
Description
Load 256-bits (composed of 4 packed double-precision (64-bit) floating-point elements) from memory into dst. mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated.
Operation
dst[255:0] := MEM[mem_addr+255:mem_addr]dst[MAX:256] := 0
208
![Page 111: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/111.jpg)
INSTRUÇÕES AVX
__m256d _mm256_mul_pd (__m256d a, __m256d b)
Description
Multiply packed double-precision (64-bit) floating-point elements in a and b,and store the results in dst.
Operation
FOR j := 0 to 3 i := j*64 dst[i+63:i] := a[i+63:i] * b[i+63:i]
ENDFOR dst[MAX:256] := 0
209
![Page 112: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/112.jpg)
INSTRUÇÕES AVX
__m256d _mm256_add_pd (__m256d a, __m256d b)
Description
Add packed double-precision (64-bit) floating-point elements in a and b, andstore the results in dst.
Operation
FOR j := 0 to 3 i := j*64 dst[i+63:i] := a[i+63:i] + b[i+63:i]
ENDFOR dst[MAX:256] := 0
210
![Page 113: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/113.jpg)
INSTRUÇÕES AVX
void _mm256_storeu_pd (double * mem_addr, __m256d a)
Description
Store 256-bits (composed of 4 packed double-precision (64-bit) floating-point elements) from a into memory. mem_addr does not need to bealigned on any particular boundary.
Operation
MEM[mem_addr+255:mem_addr] := a[255:0]
211
![Page 114: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/114.jpg)
EXERCÍCIO 8, PARTE A: DOT PRODUCT SIMD
212
double dotproduct(double *a, int *b, long long int N){long long int i;double dot = 0.0;
for(i = 0; i < N; i++)dot += a[i] * b[i];
return dot;
}
cd 8-dotProduct/ sbatch exec.batch cat XX.out
![Page 115: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/115.jpg)
SOLUÇÃO 8.1, PARTE A: DOT PRODUCT SIMD
213
double dotproduct(double *a, int *b, long long int N){long long int i;double dot = 0.0;
#pragma omp simd reduction(+ : dot)for(i = 0; i < N; i++)dot += a[i] * b[i];
return dot;
}
cd 8-dotProduct/ sbatch exec.batch cat XX.out
![Page 116: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/116.jpg)
EXERCÍCIO 8, PARTE B: DOT PRODUCT AVX
214
double dotproduct(double *a, int *b, long long int N){long long int i;double dot = 0.0;
for(i = 0; i < N; i++)dot += a[i] * b[i];
return dot;
}
cd 8-dotProduct/ sbatch exec.batch cat XX.out
![Page 117: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/117.jpg)
SOLUÇÃO 8.2, PARTE B: DOT PRODUCT AVX
215
double dotproduct(double *a, int *b, long long int N){long long int i;double dot = 0.0, partial[4];__m256d ac, va, vb, mul;
ac = _mm256_set_pd(0.0, 0.0, 0.0, 0.0).;
for(i = 0; i < N; i += 4){va = _mm256_load_pd(&a[i]);vb = _mm256_load_pd(&b[i]);mul = _mm256_mul_pd(va, vb);ac = _mm256_add_pd(ac, mul);
}_mm256_storeu_pd(partial, ac);
dot = partial[0] + partial[1] + partial[2] + partial[3];
return dot;}
cd 8-dotProduct/ sbatch exec.batch cat XX.out
![Page 118: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/118.jpg)
EXERCÍCIO 9: APLICAÇÃO PETRÓLEO
216
cd 9-petroleo/ sbatch exec.batch cat XX.out
![Page 119: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/119.jpg)
EXERCÍCIO 9: APLICAÇÃO PETRÓLEO
217
void kernel_CPU_06_mod_3DRhoCte(...){...
for(index_X = 0; index_X < nnoi; index_X++)for(index_Y = 0; index_Y < nnoj; index_Y++)for(k = 0; k < k1 - k0; k++){
...
}
...
}
cd 9-petroleo/ sbatch exec.batch cat XX.out
![Page 120: PROGRAMAÇÃO PARALELA E VETORIAL AVANÇADA](https://reader031.vdocuments.com.br/reader031/viewer/2022012417/617232f6af7fc3471e6cbcea/html5/thumbnails/120.jpg)
SOLUÇÃO 9: APLICAÇÃO PETRÓLEO
218
void kernel_CPU_06_mod_3DRhoCte(...){...
#pragma omp parallel for private(index_X, index_Y, index, k)for(index_Y = 0; index_Y < nnoj; index_Y++)for(k = 0; k < k1 - k0; k++)#pragma omp simdfor(index_X = 0; index_X < nnoi; index_X++){
...}
...
}
cd 9-petroleo/ sbatch exec.batch cat XX.out