Loading AI tools
Da Wikipédia, a enciclopédia livre
O OpenMP (do inglês Open Multi-Processing, ou Multi-processamento aberto) é uma interface de programação de aplicativo(API) para a programação multi-processo de memória compartilhada em múltiplas plataformas. Permite acrescentar simultaneidade aos programas escritos em C, C++ e Fortran sobre a base do modelo de execução fork-join. Está disponível em muitas arquiteturas, incluindo as plataforma Unix e Microsoft Windows. É constituída por um conjunto de diretivas de compilador, rotinas de biblioteca, e variáveis de ambiente que influenciam o comportamento do tempo de execução. Definido em conjunto por um grupo principal de fornecedores de hardware e de software, o OpenMP é um modelo de programação portável e escalável que proporciona aos programadores uma interface simples e flexível para o desenvolvimento de aplicações paralelas para as plataformas que vão dos computadores de escritório até os supercomputadores. Uma aplicação construída com um modelo de programação paralela híbrido pode ser executado em um cluster de computadores utilizando tanto os OpenMP e MPI, ou mais transparentemente através das extensões do OpenMP para os sistemas de memória distribuída.
A tradução deste artigo está abaixo da qualidade média aceitável. (Setembro de 2021) |
OpenMP é uma implementação de multithreading, um método de paralelização no qual o "master thread"(uma série de instruções executadas consecutivamente) forks ("bifurca") um específico número de threads escravos e uma tarefa é dividida entre eles. Os thread são então executados simultaneamente, com ambiente de execução distribuindo as threads para diferentes processadores.
A parte de código que é criada para funcionar em paralelo é marcada de acordo com uma diretriz pré-processador que criará os thread para formar a secção antes de ser executada. Cada thread tem um "id" (endereço) anexado a ele, que pode ser obtido através de uma função (chamada omp_get_thread_num() em C / C + + e OMP_GET_THREAD_NUM() em Fortran). O thread "id" é um número inteiro e o master thread possui o id "0". Após a execução do código em paralelo, os "threads" retornam ao master thread, o qual continua progressivo até o fim do programa.
Por padrão, cada thread executa a seção do código paralelo independentemente. "Construções de Partilha" pode ser usada para dividir uma tarefa entre os threads de modo que cada thread execute a sua parte do código atribuído. Ambas as Task Parallelism (Paralelismo de tarefas) e Data parallelism (Paralelismo de dados) pode ser conseguida utilizando OpenMP desta forma.
O tempo de execução comum distribui threads aos processadores de acordo com a utilização, o desempenho da máquina e outros fatores. O números de threads pode ser fixado pelo ambiente de execução baseado em variaveis de ambiente ou um código usando funções. As funções do OpenMP estão incluidas no header file (biblioteca) rotulado "omp.h" em C/C++.
O Conselho de Análise e Arquitetura (Architecture Review Board, ARB) do OpenMP publicou suas primeiras especificações da API, para o OpenMP Fortran 1.0, em Outubro de 1997. Em Outubro do ano seguinte, foi liberado o C / C + + padrão. Em 2000 viu-se a versão 2.0 das especificações, com especificações do Fortran versão 2.0 do C / C + + sendo liberado em 2002. A versão 2.5 é um combinado das especificações C / C + + / Fortran que foi liberado em 2005. A versão 3.0, lançada em maio de 2008, é a atual versão das especificações da API. Incluídas nas novas funcionalidades do 3.0 estão o conceito de tasks (Tarefas) e a task construct (Construir Tarefa). Estas novas funcionalidades estão resumidas no Apêndice F do OpenMP 3.0 specifications.
Os principais elementos do OpenMP são os construídos por "criação de fios de execução" (threads creations), "distribuição de carga do trabalho" (work sharing), "gestão do ambiente de dados" (data environment management), "sincronização de fios de execução" (thread synchronization), "tempo de execução das rotinas do usuário" (user level runtime routines) e "variáveis do ambiente" (environment variables). A diretriz em compilador C / C + + é chamado pragma (informação pragmática). A compilação de diretrizes específicas para OpenMP em C / C + + são escritas em códigos, conforme segue:
Os pragmas específicos do OpenMP estão listados a seguir:
omp paralelo. É utilizado para separar threads adicionais para a realização do trabalho incluso na construção em paralelo. O processo original será chamado master thread com ID 0. Exemplo: Exibição "Hello, world", utilizando múltiplas threads.
#include <stdio.h>
#include <omp.h>
int main(int argc, char* argv[])
{
#pragma omp parallel
printf("Hello, world.\n");
return 0;
}
Usado para especificar como atribuir um trabalho independente para um ou todos as threads.
Exemplo: inicializar o valor de uma grande variedade em paralelo, utilizando cada fio de execução para fazer parte do trabalho.
#include <stdio.h>
#include <omp.h>
int main(int argc, char **argv) {
const int N = 100000;
int i, a[N];
#pragma omp parallel for
for (i = 0; i < N; i++)
a[i] = 2 * i;
return 0;
}
Desde que foi compartilhada a programação modelo do OpenMP, a maior parte das variaveis no código do OpenMP são visíveis a todos threads por padrão. Porém algumas variaveis individuais são necessárias para evitar race conditions e existe a necessidade de passar valores entre a parte sequencial e a região paralela ( o código executado em paralelo ), para que os dados de gestão ambiental sejam introduzidos como as cláusulas atribuídas ao compartilhamento de dados colocando-lhes as diretrizes do OpenMP. Os diferentes tipos de cláusulas são:
1. static: Aqui, a todos os threads são atribuídas as iteração antes de executar o laço de repetição. As interações são divididas igualmente entre os threads por padrão. No entanto, especificando um inteiro para um parâmetro "chunk" fixará um número "chunk" de iterações sequenciadas a uma determinada lista de threads.
2. dynamic: Aqui, algumas das iterações são atribuídas a um número menor de threads. Após o término da iteração atribuída a um thread em particular, ele retorna para buscar uma das iterações restantes. O parâmetro "chunk" define o número de iterações sequenciais que são atribuídas a um thread por vez.
3. guided: Um grande "chunk" de iterações sequenciadas são atribuídos a cada thread dinamicamente (como acima). O tamanho do "chunk" diminui exponencialmente com cada atribuição sucessiva até um tamanho mínimo especificado no parâmetro chunk.
Usado para modificar / verificar o número de threads, detectar se o contexto de execução está em uma região paralela, a quantidade processadores no sistema atual, bloqueios set / unset, funções de calendário, etc.
É um método para alterar os recursos de execução de aplicativos OpenMP. Usado para controlar os loops de iterações, número de threads padrão, etc. Por exemplo OMP_NUM_THREADS é usado para especificar o número de tópicos para uma aplicação.
Nesta seção, alguns programas de exemplo são fornecidos para ilustrar os conceitos explicados acima.
Este é um programa básico, que exerce o parallel, private e as barrier directives, bem como as funções omp_get_thread_num e omp_get_num_threads (não confundir).
package omp.hello;
import jomp.runtime.OMP;
public class Hello_Normal {
public static void main(String[] args) {
int id;
OMP.setNumThreads(15);
//omp parallel private(id)
{
id = OMP.getThreadNum();
System.out.println("Hello from thread: " + id);
}
}
}
#include <omp.h>
#include <stdio.h>
int main (int argc, char *argv[]) {
int th_id, nthreads;
#pragma omp parallel private(th_id)
{
th_id = omp_get_thread_num();
printf("Hello World from thread %d\n", th_id);
#pragma omp barrier
if ( th_id == 0 ) {
nthreads = omp_get_num_threads();
printf("There are %d threads\n",nthreads);
}
}
return 0;
}
#include <omp.h>
#include <iostream>
int main (int argc, char *argv[]) {
int th_id, nthreads;
#pragma omp parallel private(th_id)
{
th_id = omp_get_thread_num();
std::cout << "Hello World from thread" << th_id << "\n";
#pragma omp barrier
if ( th_id == 0 ) {
nthreads = omp_get_num_threads();
std::cout << "There are " << nthreads << " threads\n";
}
}
return 0;
}
PROGRAM HELLO
INTEGER ID, NTHRDS
INTEGER OMP_GET_THREAD_NUM, OMP_GET_NUM_THREADS
C$OMP PARALLEL PRIVATE(ID)
ID = OMP_GET_THREAD_NUM()
PRINT *, 'HELLO WORLD FROM THREAD', ID
C$OMP BARRIER
IF ( ID .EQ. 0 ) THEN
NTHRDS = OMP_GET_NUM_THREADS()
PRINT *, 'THERE ARE', NTHRDS, 'THREADS'
END IF
C$OMP END PARALLEL
END
program hello90
use omp_lib
integer:: id, nthreads
!$omp parallel private(id)
id = omp_get_thread_num()
write (*,*) 'Hello World from thread', id
!$omp barrier
if ( id == 0 ) then
nthreads = omp_get_num_threads()
write (*,*) 'There are', nthreads, 'threads'
end if
!$omp end parallel
end program
A aplicação de cláusulas OpenMp são ilustradas nos simples exemplos dessa seção. Esse pedaço de código abaixo mostra os elementos do vetor "b", demonstrando uma simples operação com os elementos do vetor "a". A parabolização é feita pelo diretivo OpenMP "#pragma". A sincronização de tarefas é dinâmica. Note como a interação dos pontos "j" e "k" tem que ser feito pilha de execução, portanto para fazer a tarefa total que lhe foi atribuída e atualizar a parte alocada da matriz "b", ao mesmo tempo como as outras threads.
#define CHUNKSIZE 1 /*define o tamanho do pedaço com 1 iteração contigua*/
/*forks saindo das threads*/
#pragma omp parallel private(j,k)
{
/*nicia a construção de partilha*/
#pragma omp for schedule(dynamic, CHUNKSIZE)
for(i = 2; i <= N-1; i++)
for(j = 2; j <= i; j++)
for(k = 1; k <= M; k++)
b[i][j] += a[i-1][j]/k + a[i+1][j]/k;
}
O próximo pedaço de código é um uso comum da reduction para calcular somas reduzidas. Aqui, nós adicionamos todos os elementos de um vetor "a" com um "i" contador, usando um for-loop que nós paralalizamos usando direvtives OpenMP e reduction. O cronograma permaneceu estático.
#define N 10000 /*tamanho de um*/
void calculate(int); /*A função calcula os elementos de um*/
int i;
long w;
long a[N];
calculate(a);
long sum = 0;
/*forks saindo das threads e começando a construção de partilha*/
#pragma omp parallel for private(w) reduction(+:sum) schedule(static,1)
for(i = 0; i < N; i++)
{
w = i*i;
sum = sum + w*a[i];
}
printf("\n %li",sum);
Um equivalente, porém menos elegante, a execução do código acima é para criar uma soma variável local para cada thread (loc_sum "), e fazer uma atualização protegido da variável global" soma "no final do processo, através da directiva" crítical ". Note que essa proteção é fundamental, como foi explicado em outro lugar.
...
long sum = 0, loc_sum = 0;
/*forks saindo das threads e começando a construção de partilha*/
#pragma omp parallel for private(w,loc_sum) schedule(static,1)
{
for(i = 0; i < N; i++)
{
w = i*i;
loc_sum = loc_sum + w*a[i];
}
#pragma omp critical
sum = sum + loc_sum;
}
printf("\n %li",sum);
OpenMP foi implementada em vários compiladores comerciais. Por exemplo, Visual C++ o suporta (nas edicoes do "Professional and Team System"[1]), assim como "Intel Parellel Studio" para diversos processadores.[2] Compiladores e ferramentas Sun Studio suportam as ultimas especificacoes com ressalvas na produtividade para as plataformas Solaris SO e Linux.Os compiladores Fortran, C e C + + dO Portland Group também suportam OpenMP 2,5. O GCC também apoiou OpenMP desde a versão 4.2.
Alguns compiladores logo foram implementados para OpenMP 3.0, incluindo:
Sun Studio 12 update 1 tem plena aplicação do OpenMP 3.0.[4]
Prós
nenhuma mudança dramática para o código é necessário.
são tratadas como comentários quando compiladores seqüenciais são utilizados.
quando paralelizado com OpenMP.
Contras
Pode-se esperar obter N vezes menos no tempo de execução do "wall clock" (ou N vezes speed up) quando executado um programa paralelizado utilizando OpenMP em uma plataforma de processador N. No entanto, isso raramente é o caso, devido às seguintes razões:
Uma grande parte do programa não pode ser paralelizada por OpenMP, o que significa que o limite teórico máximo de aceleração é de acordo com a lei de Amdahl.
N processadores em um SMP pode ter N vezes o poder de computação, mas a bandwidth de memória normalmente não escala até N vezes. Muitas vezes, o caminho de memória original é partilhada por vários processadores e a degradação do desempenho pode ser observada quando concorrem para a largura de banda de memória partilhada. Muitos outros problemas comuns que afetam o aumento de velocidade final em computação paralela também se aplicam a OpenMP, como balanceamento de carga e sobrecarga de sincronização.
Alguns vendedores recomendam a configuração processor afinity em threads OpenMP para associá-los com núcleos de processador específico.[5][6][7] Isso minimiza a migração thread e o custo da comunicação entre o switch e os núcleos. Também melhora a localização dos dados e reduz o tráfego de coerência-cache entre os núcleos (ou processadores).
Existem alguns pontos de referência OpenMP de dominio público que o usuário pode experimentar:
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.