OpenMP 指示詞
提供 OpenMP API 中使用的指示詞連結。
Visual C++支援下列 OpenMP 指示詞。
針對平行工作共用:
指示詞 | 描述 |
---|---|
parallel | 定義平行區域,這是由多個線程平行執行的程序代碼。 |
for | 讓平行區域內的迴圈中 for 完成的工作在線程之間分割。 |
sections | 識別要分割於所有線程之間的程式代碼區段。 |
single | 可讓您指定程式代碼區段應該在單個線程上執行,而不一定是主線程。 |
針對主要線程和同步處理:
指示詞 | 描述 |
---|---|
master | 指定只有主線程應該執行程序的區段。 |
critical | 指定程式代碼一次只在一個線程上執行。 |
barrier | 同步處理小組中的所有線程;所有線程都會暫停在屏障上,直到所有線程執行屏障為止。 |
atomic | 指定將會以不可部分完成方式更新的記憶體位置。 |
flush | 指定所有線程對於所有共享物件都有相同的記憶體檢視。 |
命令 | 指定平行化 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
的範例,請參閱 master。
critical
指定程式代碼一次只能在一個線程上執行。
#pragma omp critical [(name)]
{
code_block
}
參數
name
(選擇性)識別重要程式代碼的名稱。 名稱必須以括弧括住。
備註
指示 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
讓平行區域內的迴圈中 for
完成的工作在線程之間分割。
#pragma omp [parallel] for [clauses]
for_statement
參數
第
(選擇性)零個或多個子句,請參閱 一 節。
for_statement
迴圈 for
。 如果迴圈中的使用者程式代碼變更索引變數, for
則未定義的行為將會產生。
備註
指示 for
詞支援下列子句:
如果parallel
也指定 ,clauses
可以是 或 for
指示詞接受parallel
的任何 子句,但 除外nowait
。
如需詳細資訊,請參閱 2.4.1 for construct。
範例
// 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
master
指定只有主線程應該執行程序的區段。
#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
排序
指定平行化 for
迴圈下的程式代碼應該像循序迴圈一樣執行。
#pragma omp ordered
structured-block
備註
指示ordered
詞必須位於 的動態範圍內,或是parallel for
使用 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
}
參數
第
(選擇性)零個或多個子句,請參閱 一 節。
備註
指示 parallel
詞支援下列子句:
parallel
也可以與 for 和 sections 指示詞搭配使用。
如需詳細資訊,請參閱 2.3 平行建構。
範例
下列範例示範如何設定線程數目並定義平行區域。 線程數目預設等於電腦上的邏輯處理器數目。 例如,如果您有一部實體處理器已啟用超線程的計算機,則會有兩個邏輯處理器和兩個線程。 不同機器上的輸出順序可能會有所不同。
// 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
}
}
參數
第
(選擇性)零個或多個子句,請參閱 一 節。
備註
指示 sections
詞可以包含零個或多個 section
指示詞。
指示 sections
詞支援下列子句:
如果parallel
也指定 ,clauses
可以是 或 sections
指示詞接受parallel
的任何 子句,但 除外nowait
。
如需詳細資訊,請參閱 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
}
參數
第
(選擇性)零個或多個子句,請參閱 一 節。
備註
指示 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 關鍵詞的線程屬性為基礎;套用至threadprivate
的限制__declspec(thread)
。 例如, threadprivate
變數會存在於進程啟動的任何線程中,而不只是屬於平行區域所繁衍線程小組一部分的線程。 請注意此實作詳細數據;您可能會注意到,使用者定義類型的建構 threadprivate
函式會更常呼叫,然後預期。
您可以在行程啟動時以靜態方式載入的 DLL 中使用 threadprivate
,不過您無法threadprivate
在任何透過 LoadLibrary 載入的 DLL 中使用,例如使用 /DELAYLOAD 載入的 DLL(延遲載入匯入),這也會使用 LoadLibrary
。
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。