Diferença entre #pragma omp parallel e #pragma omp parallel para

Dec 11 2020

Eu sou novo OpenMPe tenho tentado executar um programa que adiciona duas matrizes usando OpenMP. No tutorial do OpenMP, aprendi que precisamos usar #pragma omp parallel for ao usar o OpenMP no loop for . Mas eu também tentei a mesma coisa com #pragma omp parallel e também está me dando a saída correta. Abaixo estão os trechos de código do que estou tentando transmitir.

#pragma omp parallel for
{
      for(int i=0;i<n;i++)
       {  
            c[i]=a[i]+b[i];
       }
}

e

 #pragma omp parallel
{
      for(int i=0;i<n;i++)
       {  
            c[i]=a[i]+b[i];
       }
}

Qual é a diferença entre esses dois?

Respostas

5 dreamcrash Dec 11 2020 at 15:14

o

#pragma omp parallel:

criará um parallel regioncom uma equipe de threads, onde cada thread executará todo o bloco de código que o parallel regioninclui.

No OpenMP 5.1 pode-se ler uma descrição mais formal:

Quando uma thread encontra uma construção paralela , uma equipe de threads é criada para executar a região paralela (..). O encadeamento que encontrou a construção paralela se torna o encadeamento principal da nova equipe, com um número de encadeamento zero para a duração da nova região paralela. Todos os threads na nova equipe, incluindo o thread principal, executam a região. Depois que a equipe é criada, o número de threads na equipe permanece constante durante a região paralela.

O:

#pragma omp parallel for

irá criar um parallel region(como descrito antes), e para o threadsdessa região as iterações do loop que ele inclui serão atribuídas, usando o default chunk size, e o default scheduleque é normalmente static . Tenha em mente, entretanto, que o default schedulepode diferir entre as diferentes implementações concretas da OpenMPnorma.

No OpenMP 5.1 você pode ler uma descrição mais formal:

A construção de loop de compartilhamento de trabalho especifica que as iterações de um ou mais loops associados serão executadas em paralelo por threads na equipe no contexto de suas tarefas implícitas. As iterações são distribuídas por threads que já existem na equipe que está executando a região paralela à qual a região do loop de compartilhamento de trabalho se liga .

Além disso ,

A construção de loop paralelo é um atalho para especificar uma construção paralela contendo uma construção de loop com um ou mais loops associados e nenhuma outra instrução.

Ou informalmente, #pragma omp parallel foré uma combinação do construtor #pragma omp parallelcom #pragma omp for. No seu caso, isso significaria que:

#pragma omp parallel for
{
      for(int i=0;i<n;i++)
       {  
            c[i]=a[i]+b[i];
       }
}

é semanticamente e logicamente o mesmo que:

#pragma omp parallel
{
      #pragma omp for
      for(int i=0;i<n;i++)
       {  
            c[i]=a[i]+b[i];
       }
}

TL; DR: Em seu exemplo, com #pragma omp parallel foro loop será paralelizado entre os threads ( ou seja, as iterações do loop serão divididas entre os threads), enquanto com #pragma omp parallel todos os threads executará (em paralelo) todas as iterações do loop.

Para torná-lo mais ilustrativo, com 4tópicos #pragma omp parallel, resultaria em algo como:

enquanto que #pragma omp parallel forcom um chunk_size=1e um estático schedule resultaria em algo como:

Em termos de código, o loop seria transformado em algo logicamente semelhante a:

for(int i=omp_get_thread_num(); i < n; i+=omp_get_num_threads())
{  
    c[i]=a[i]+b[i];
}

onde omp_get_thread_num ()

A rotina omp_get_thread_num retorna o número do encadeamento, dentro da equipe atual, do encadeamento de chamada.

e omp_get_num_threads ()

Retorna o número de threads na equipe atual. Em uma seção sequencial do programa omp_get_num_threads retorna 1.

ou em outras palavras for(int i = THREAD_ID; i < n; i += TOTAL_THREADS),. Com THREAD_IDvariando de 0a TOTAL_THREADS - 1, e TOTAL_THREADSrepresentando o número total de threads da equipe criados na região paralela.

Aprendi que precisamos usar #pragma omp parallel for ao usar o OpenMP no loop for. Mas eu também tentei a mesma coisa com #pragma omp parallel e também está me dando a saída correta.

Ele fornece a mesma saída, porque em seu código:

 c[i]=a[i]+b[i];

array ae array bsão apenas lidos, e array c[i]é o único que está sendo atualizado, e seu valor não depende de quantas vezes a iteração iserá executada. No entanto, com #pragma omp parallel forcada thread será atualizado o seu próprio i, enquanto com #pragma omp parallelthreads estará atualizando os mesmos is, portanto, substituindo os valores uns dos outros.

Agora tente fazer o mesmo com o seguinte código:

#pragma omp parallel for
{
      for(int i=0;i<n;i++)
       {  
            c[i]= c[i] + a[i] + b[i];
       }
}

e

#pragma omp for
{
      for(int i=0;i<n;i++)
       {  
            c[i] = c[i] + a[i] + b[i];
       }
}

você notará imediatamente a diferença.

2 DanielLangr Dec 11 2020 at 15:16

No segundo caso, o loop não é paralelizado. Ou seja, todo o loop é executado em cada thread . Geralmente, tudo o que está dentro da região paralela é executado por todos os threads.

Além disso, você pode paralelizar o loop na região paralela já existente da seguinte maneira:

#pragma omp parallel
{
  #pragma omp for
  for (int i = 0; i < n; i++)
    c[i] = a[i] + b[i];
}