다음을 통해 공유


OpenMP 지시문

OpenMP API에 사용되는 지시문에 대한 링크를 제공합니다.

Visual C++는 다음 OpenMP 지시문을 지원합니다.

병렬 작업 공유의 경우:

지시문 설명
parallel 여러 스레드에서 병렬로 실행되는 코드인 병렬 영역을 정의합니다.
for 병렬 영역 내의 for 루프에서 수행된 작업이 스레드 간에 분할되도록 합니다.
sections 모든 스레드로 나눌 코드 섹션을 식별합니다.
single 코드 섹션을 주 스레드가 아닌 단일 스레드에서 실행되도록 지정할 수 있습니다.

주 스레드 및 동기화의 경우:

지시문 설명
master 주 스레드만 프로그램의 섹션을 실행되도록 지정합니다.
중요 코드가 한 번에 하나의 스레드에서만 실행되도록 지정합니다.
barrier 팀의 모든 스레드를 동기화합니다. 모든 스레드가 장벽을 실행할 때까지 모든 스레드가 장벽에서 일시 중지됩니다.
atomic 원자성으로 업데이트할 메모리 위치를 지정합니다.
flush 모든 스레드가 모든 공유 개체에 대해 동일한 메모리 뷰를 가지게 지정합니다.
ordered 병렬 처리된 for 루프 아래의 코드를 순차 루프처럼 실행되도록 지정합니다.

데이터 환경의 경우:

지시문 설명
threadprivate 변수가 스레드에 대한 프라이빗임을 지정합니다.

atomic

원자성으로 업데이트할 메모리 위치를 지정합니다.

#pragma omp atomic
   expression

매개 변수

expression
둘 이상의 쓰기로부터 보호하려는 메모리 위치의 lvalue가 있는 문입니다.

설명

지시문은 atomic 절을 지원하지 않습니다.

자세한 내용은 2.6.4 원자성 구문을 참조하세요.

예시

// omp_atomic.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

#define MAX 10

int main() {
   int count = 0;
   #pragma omp parallel num_threads(MAX)
   {
      #pragma omp atomic
      count++;
   }
   printf_s("Number of threads: %d\n", count);
}
Number of threads: 10

barrier

팀의 모든 스레드를 동기화합니다. 모든 스레드가 장벽을 실행할 때까지 모든 스레드가 장벽에서 일시 중지됩니다.

#pragma omp barrier

설명

지시문은 barrier 절을 지원하지 않습니다.

자세한 내용은 2.6.3 barrier 지시문을 참조 하세요.

예시

사용 barrier방법에 대한 샘플은 마스터를 참조하세요.

중요

코드가 한 번에 하나의 스레드에서만 실행되도록 지정합니다.

#pragma omp critical [(name)]
{
   code_block
}

매개 변수

이름
(선택 사항) 중요한 코드를 식별하는 이름입니다. 이름은 괄호로 묶어야 합니다.

설명

지시문은 critical 절을 지원하지 않습니다.

자세한 내용은 2.6.2 중요 구문을 참조하세요.

예시

// omp_critical.cpp
// compile with: /openmp
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

#define SIZE 10

int main()
{
    int i;
    int max;
    int a[SIZE];

    for (i = 0; i < SIZE; i++)
    {
        a[i] = rand();
        printf_s("%d\n", a[i]);
    }

    max = a[0];
    #pragma omp parallel for num_threads(4)
        for (i = 1; i < SIZE; i++)
        {
            if (a[i] > max)
            {
                #pragma omp critical
                {
                    // compare a[i] and max again because max
                    // could have been changed by another thread after
                    // the comparison outside the critical section
                    if (a[i] > max)
                        max = a[i];
                }
            }
        }

    printf_s("max = %d\n", max);
}
41
18467
6334
26500
19169
15724
11478
29358
26962
24464
max = 29358

flush

모든 스레드가 모든 공유 개체에 대해 동일한 메모리 뷰를 가지게 지정합니다.

#pragma omp flush [(var)]

매개 변수

var
(선택 사항) 동기화하려는 개체를 나타내는 변수의 쉼표로 구분된 목록입니다. var을 지정하지 않으면 모든 메모리가 플러시됩니다.

설명

지시문은 flush 절을 지원하지 않습니다.

자세한 내용은 2.6.5 flush 지시문을 참조 하세요.

예시

// omp_flush.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

void read(int *data) {
   printf_s("read data\n");
   *data = 1;
}

void process(int *data) {
   printf_s("process data\n");
   (*data)++;
}

int main() {
   int data;
   int flag;

   flag = 0;

   #pragma omp parallel sections num_threads(2)
   {
      #pragma omp section
      {
         printf_s("Thread %d: ", omp_get_thread_num( ));
         read(&data);
         #pragma omp flush(data)
         flag = 1;
         #pragma omp flush(flag)
         // Do more work.
      }

      #pragma omp section
      {
         while (!flag) {
            #pragma omp flush(flag)
         }
         #pragma omp flush(data)

         printf_s("Thread %d: ", omp_get_thread_num( ));
         process(&data);
         printf_s("data = %d\n", data);
      }
   }
}
Thread 0: read data
Thread 1: process data
data = 2

-

병렬 영역 내의 for 루프에서 수행된 작업이 스레드 간에 분할되도록 합니다.

#pragma omp [parallel] for [clauses]
   for_statement

매개 변수


(선택 사항) 0개 이상의 절은 주의 섹션을 참조하세요 .

for_statement
루프입니다 for . 루프의 사용자 코드가 인덱스 변수를 for 변경하는 경우 정의되지 않은 동작이 발생합니다.

설명

지시문은 for 다음 절을 지원합니다.

또한 지정 된 경우 parallel 를 제외 하 고 nowait또는 for 지시문에 parallel 의해 허용 되는 모든 절 수 clauses 있습니다.

자세한 내용은 구문에 대한 2.4.1을 참조하세요.

예시

// omp_for.cpp
// compile with: /openmp
#include <stdio.h>
#include <math.h>
#include <omp.h>

#define NUM_THREADS 4
#define NUM_START 1
#define NUM_END 10

int main() {
   int i, nRet = 0, nSum = 0, nStart = NUM_START, nEnd = NUM_END;
   int nThreads = 0, nTmp = nStart + nEnd;
   unsigned uTmp = (unsigned((abs(nStart - nEnd) + 1)) *
                               unsigned(abs(nTmp))) / 2;
   int nSumCalc = uTmp;

   if (nTmp < 0)
      nSumCalc = -nSumCalc;

   omp_set_num_threads(NUM_THREADS);

   #pragma omp parallel default(none) private(i) shared(nSum, nThreads, nStart, nEnd)
   {
      #pragma omp master
      nThreads = omp_get_num_threads();

      #pragma omp for
      for (i=nStart; i<=nEnd; ++i) {
            #pragma omp atomic
            nSum += i;
      }
   }

   if  (nThreads == NUM_THREADS) {
      printf_s("%d OpenMP threads were used.\n", NUM_THREADS);
      nRet = 0;
   }
   else {
      printf_s("Expected %d OpenMP threads, but %d were used.\n",
               NUM_THREADS, nThreads);
      nRet = 1;
   }

   if (nSum != nSumCalc) {
      printf_s("The sum of %d through %d should be %d, "
               "but %d was reported!\n",
               NUM_START, NUM_END, nSumCalc, nSum);
      nRet = 1;
   }
   else
      printf_s("The sum of %d through %d is %d\n",
               NUM_START, NUM_END, nSum);
}
4 OpenMP threads were used.
The sum of 1 through 10 is 55

마스터

주 스레드만 프로그램의 섹션을 실행되도록 지정합니다.

#pragma omp master
{
   code_block
}

설명

지시문은 master 절을 지원하지 않습니다.

자세한 내용은 2.6.1 마스터 구문을 참조하세요.

코드 섹션을 주 스레드가 아닌 단일 스레드에서 실행하도록 지정하려면 대신 단일 지시문을 사용합니다.

예시

// compile with: /openmp
#include <omp.h>
#include <stdio.h>

int main( )
{
    int a[5], i;

    #pragma omp parallel
    {
        // Perform some computation.
        #pragma omp for
        for (i = 0; i < 5; i++)
            a[i] = i * i;

        // Print intermediate results.
        #pragma omp master
            for (i = 0; i < 5; i++)
                printf_s("a[%d] = %d\n", i, a[i]);

        // Wait.
        #pragma omp barrier

        // Continue with the computation.
        #pragma omp for
        for (i = 0; i < 5; i++)
            a[i] += i;
    }
}
a[0] = 0
a[1] = 1
a[2] = 4
a[3] = 9
a[4] = 16

ordered

병렬 처리된 for 루프 아래의 코드를 순차 루프처럼 실행되도록 지정합니다.

#pragma omp ordered
   structured-block

설명

지시문은 ordered 절이 있는 for 또는 parallel for construct ordered동적 범위 내에 있어야 합니다.

지시문은 ordered 절을 지원하지 않습니다.

자세한 내용은 2.6.6 정렬된 구문을 참조하세요.

예시

// omp_ordered.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

static float a[1000], b[1000], c[1000];

void test(int first, int last)
{
    #pragma omp for schedule(static) ordered
    for (int i = first; i <= last; ++i) {
        // Do something here.
        if (i % 2)
        {
            #pragma omp ordered
            printf_s("test() iteration %d\n", i);
        }
    }
}

void test2(int iter)
{
    #pragma omp ordered
    printf_s("test2() iteration %d\n", iter);
}

int main( )
{
    int i;
    #pragma omp parallel
    {
        test(1, 8);
        #pragma omp for ordered
        for (i = 0 ; i < 5 ; i++)
            test2(i);
    }
}
test() iteration 1
test() iteration 3
test() iteration 5
test() iteration 7
test2() iteration 0
test2() iteration 1
test2() iteration 2
test2() iteration 3
test2() iteration 4

parallel

여러 스레드에서 병렬로 실행되는 코드인 병렬 영역을 정의합니다.

#pragma omp parallel [clauses]
{
   code_block
}

매개 변수


(선택 사항) 0개 이상의 절은 주의 섹션을 참조하세요 .

설명

지시문은 parallel 다음 절을 지원합니다.

parallel는 for 및 sections 지시문과 함께 사용할 수도 있습니다.

자세한 내용은 2.3 병렬 구문을 참조하세요.

예시

다음 샘플에서는 스레드 수를 설정하고 병렬 영역을 정의하는 방법을 보여 줍니다. 스레드 수는 기본적으로 컴퓨터의 논리 프로세서 수와 같습니다. 예를 들어 하이퍼스레딩을 사용하도록 설정된 물리적 프로세서가 하나 있는 컴퓨터가 있는 경우 논리 프로세서 2개와 스레드 2개가 있습니다. 출력 순서는 컴퓨터마다 다를 수 있습니다.

// omp_parallel.cpp
// compile with: /openmp
#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 %d\n", i);
   }
}
Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3

sections

모든 스레드로 나눌 코드 섹션을 식별합니다.

#pragma omp [parallel] sections [clauses]
{
   #pragma omp section
   {
      code_block
   }
}

매개 변수


(선택 사항) 0개 이상의 절은 주의 섹션을 참조하세요 .

설명

지시문에는 sections 0개 이상의 section 지시문이 포함될 수 있습니다.

지시문은 sections 다음 절을 지원합니다.

또한 지정 된 경우 parallel 를 제외 하 고 nowait또는 sections 지시문에 parallel 의해 허용 되는 모든 절 수 clauses 있습니다.

자세한 내용은 2.4.2 섹션 구문을 참조하세요.

예시

// omp_sections.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

int main() {
    #pragma omp parallel sections num_threads(4)
    {
        printf_s("Hello from thread %d\n", omp_get_thread_num());
        #pragma omp section
        printf_s("Hello from thread %d\n", omp_get_thread_num());
    }
}
Hello from thread 0
Hello from thread 0

single

코드 섹션을 주 스레드가 아닌 단일 스레드에서 실행되도록 지정할 수 있습니다.

#pragma omp single [clauses]
{
   code_block
}

매개 변수


(선택 사항) 0개 이상의 절은 주의 섹션을 참조하세요 .

설명

지시문은 single 다음 절을 지원합니다.

자세한 내용은 2.4.3 단일 구문을 참조하세요.

코드 섹션이 주 스레드에서만 실행되도록 지정하려면 대신 master 지시문을 사용합니다.

예시

// omp_single.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

int main() {
   #pragma omp parallel num_threads(2)
   {
      #pragma omp single
      // Only a single thread can read the input.
      printf_s("read input\n");

      // Multiple threads in the team compute the results.
      printf_s("compute results\n");

      #pragma omp single
      // Only a single thread can write the output.
      printf_s("write output\n");
    }
}
read input
compute results
compute results
write output

threadprivate

변수가 스레드에 대한 프라이빗임을 지정합니다.

#pragma omp threadprivate(var)

매개 변수

var
스레드에 대해 비공개로 만들려는 변수의 쉼표로 구분된 목록입니다. var 은 전역 또는 네임스페이스 범위 변수 또는 로컬 정적 변수여야 합니다.

설명

지시문은 threadprivate 절을 지원하지 않습니다.

threadprivate 지시어는 __declspec 키워드를 사용하는 thread 특성을 기반으로 합니다 .__declspec(thread)에 대한 제한은 threadprivate에 적용됩니다. 예를 들어 threadprivate 변수는 병렬 지역에 의해 생성된 스레드 팀의 일부인 스레드뿐만 아니라 프로세스에서 시작된 모든 스레드에 존재합니다. 이 구현 세부 정보를 알고 있어야 합니다. 사용자 정의 형식에 threadprivate 대한 생성자가 더 자주 호출되는 것을 알 수 있습니다.

프로세스 시작 시 정적으로 로드되는 DLL에서 사용할 threadprivate 수 있지만 , 또한 사용하는 LoadLibrary/DELAYLOAD(지연 로드 가져오기)로 로드되는 DLL과 같이 LoadLibrary를 통해 로드되는 DLL에는 사용할 threadprivate 수 없습니다.

threadprivate 소멸 가능한 형식의 변수는 소멸자를 호출하도록 보장되지 않습니다. 예시:

struct MyType
{
    ~MyType();
};

MyType threaded_var;
#pragma omp threadprivate(threaded_var)
int main()
{
    #pragma omp parallel
    {}
}

사용자는 병렬 영역을 구성하는 스레드가 종료되는 시기를 제어할 수 없습니다. 프로세스가 종료될 때 해당 스레드가 있는 경우 스레드는 프로세스 종료에 대한 알림을 받지 않으며, 소멸자는 종료되는 스레드(여기, 기본 스레드)를 제외한 모든 스레드에서 호출 threaded_var 되지 않습니다. 따라서 코드는 변수의 threadprivate 적절한 소멸을 계산해서는 안 됩니다.

자세한 내용은 2.7.1 threadprivate 지시문을 참조 하세요.

예시

사용 threadprivate샘플은 private을 참조하세요.