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 지시문을 참조 하세요.