共用方式為


OpenMP 指示詞

提供 OpenMP API 中使用的指示詞連結。

Visual C++ 支援下列 OpenMP 指示詞。

針對平行工作共用:

指示詞 描述
parallel 定義平列區域,這是由多個執行緒平行執行的程式碼。
for 讓平列區域內的迴圈中 for 完成的工作線上程之間分割。
部分 識別要分割于所有線程之間的程式碼區段。
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 完成的工作線上程之間分割。

#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

區段

識別要分割于所有線程之間的程式碼區段。

#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