Klausul OpenMP

Menyediakan tautan ke klausul yang digunakan dalam OPENMP API.

Visual C++ mendukung klausul OpenMP berikut.

Untuk atribut umum:

Klausul Deskripsi
if Menentukan apakah perulangan harus dijalankan secara paralel atau dalam serial.
num_threads Mengatur jumlah utas dalam tim utas.
Memerintahkan Diperlukan pada paralel untuk pernyataan jika arahan yang diurutkan akan digunakan dalam perulangan.
jadwal Berlaku untuk direktif .
nowait Mengambil alih penghambat implisit dalam arahan.

Untuk atribut berbagi data:

Klausul Deskripsi
private Menentukan bahwa setiap utas harus memiliki instans variabelnya sendiri.
firstprivate Menentukan bahwa setiap utas harus memiliki instans variabel sendiri, dan bahwa variabel harus diinisialisasi dengan nilai variabel, karena ada sebelum konstruksi paralel.
lastprivate Menentukan bahwa versi konteks penutup variabel diatur sama dengan versi privat dari utas mana pun yang menjalankan iterasi akhir (untuk konstruksi perulangan) atau bagian terakhir (bagian #pragma).
Bersama Menentukan bahwa satu atau beberapa variabel harus dibagikan di antara semua utas.
Default Menentukan perilaku variabel yang tidak terlingkup di wilayah paralel.
Pengurangan Menentukan bahwa satu atau beberapa variabel yang bersifat privat untuk setiap utas adalah subjek operasi pengurangan di akhir wilayah paralel.
copyin Memungkinkan utas untuk mengakses nilai utas utama, untuk variabel threadprivate .
copyprivate Menentukan bahwa satu atau beberapa variabel harus dibagikan di antara semua utas.

copyin

Memungkinkan utas untuk mengakses nilai utas utama, untuk variabel threadprivate .

copyin(var)

Parameter

var
Variabel threadprivate yang akan diinisialisasi dengan nilai variabel di utas utama, seperti yang ada sebelum konstruksi paralel.

Keterangan

copyin berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat salinan 2.7.2.7.

Contoh

Lihat threadprivate untuk contoh penggunaan copyin.

copyprivate

Menentukan bahwa satu atau beberapa variabel harus dibagikan di antara semua utas.

copyprivate(var)

Parameter

var
Satu atau beberapa variabel untuk dibagikan. Jika lebih dari satu variabel ditentukan, pisahkan nama variabel dengan koma.

Keterangan

copyprivate berlaku untuk direktif tunggal .

Untuk informasi selengkapnya, lihat copyprivate 2.7.2.8.

Contoh

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

float x, y, fGlobal = 1.0;
#pragma omp threadprivate(x, y)

float get_float() {
   fGlobal += 0.001;
   return fGlobal;
}

void use_float(float f, int t) {
   printf_s("Value = %f, thread = %d\n", f, t);
}

void CopyPrivate(float a, float b) {
   #pragma omp single copyprivate(a, b, x, y)
   {
      a = get_float();
      b = get_float();
      x = get_float();
      y = get_float();
    }

   use_float(a, omp_get_thread_num());
   use_float(b, omp_get_thread_num());
   use_float(x, omp_get_thread_num());
   use_float(y, omp_get_thread_num());
}

int main() {
   float a = 9.99, b = 123.456;

   printf_s("call CopyPrivate from a single thread\n");
   CopyPrivate(9.99, 123.456);

   printf_s("call CopyPrivate from a parallel region\n");
   #pragma omp parallel
   {
      CopyPrivate(a, b);
   }
}
call CopyPrivate from a single thread
Value = 1.001000, thread = 0
Value = 1.002000, thread = 0
Value = 1.003000, thread = 0
Value = 1.004000, thread = 0
call CopyPrivate from a parallel region
Value = 1.005000, thread = 0
Value = 1.005000, thread = 1
Value = 1.006000, thread = 0
Value = 1.006000, thread = 1
Value = 1.007000, thread = 0
Value = 1.007000, thread = 1
Value = 1.008000, thread = 0
Value = 1.008000, thread = 1

Default

Menentukan perilaku variabel yang tidak terlingkup di wilayah paralel.

default(shared | none)

Keterangan

shared, yang berlaku jika default klausul tidak ditentukan, berarti bahwa variabel apa pun di wilayah paralel akan diperlakukan seolah-olah ditentukan dengan klausul bersama . none berarti bahwa setiap variabel yang digunakan di wilayah paralel yang tidak tercakup dalam klausul privat, bersama, pengurangan, firstprivate, atau lastprivate akan menyebabkan kesalahan kompilator.

default berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat default 2.7.2.5.

Contoh

Lihat privat untuk contoh penggunaan default.

firstprivate

Menentukan bahwa setiap utas harus memiliki instans variabel sendiri, dan bahwa variabel harus diinisialisasi dengan nilai variabel, karena ada sebelum konstruksi paralel.

firstprivate(var)

Parameter

var
Variabel untuk memiliki instans di setiap utas dan yang akan diinisialisasi dengan nilai variabel, karena ada sebelum konstruksi paralel. Jika lebih dari satu variabel ditentukan, pisahkan nama variabel dengan koma.

Keterangan

firstprivate berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat 2.7.2.2 firstprivate.

Contoh

Untuk contoh penggunaan firstprivate, lihat contoh secara privat.

if (OpenMP)

Menentukan apakah perulangan harus dijalankan secara paralel atau dalam serial.

if(expression)

Parameter

expression
Ekspresi integral yang, jika dievaluasi ke true (bukan nol), menyebabkan kode di wilayah paralel dijalankan secara paralel. Jika ekspresi mengevaluasi ke false (nol), wilayah paralel dijalankan dalam serial (dengan satu utas).

Keterangan

if berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat konstruksi paralel 2.3.

Contoh

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

void test(int val)
{
    #pragma omp parallel if (val)
    if (omp_in_parallel())
    {
        #pragma omp single
        printf_s("val = %d, parallelized with %d threads\n",
                 val, omp_get_num_threads());
    }
    else
    {
        printf_s("val = %d, serialized\n", val);
    }
}

int main( )
{
    omp_set_num_threads(2);
    test(0);
    test(2);
}
val = 0, serialized
val = 2, parallelized with 2 threads

lastprivate

Menentukan bahwa versi konteks penutup variabel diatur sama dengan versi privat dari utas mana pun yang menjalankan iterasi akhir (untuk konstruksi perulangan) atau bagian terakhir (bagian #pragma).

lastprivate(var)

Parameter

var
Variabel yang diatur sama dengan versi privat dari utas mana pun yang menjalankan iterasi akhir (konstruksi for-loop) atau bagian terakhir (bagian #pragma).

Keterangan

lastprivate berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat 2.7.2.3 lastprivate.

Contoh

Lihat jadwal untuk contoh penggunaan lastprivate klausa.

nowait

Mengambil alih penghambat implisit dalam arahan.

nowait

Keterangan

nowait berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat konstruksi 2.4.1, 2.4.2 bagian, dan konstruksi tunggal 2.4.3.

Contoh

// omp_nowait.cpp
// compile with: /openmp /c
#include <stdio.h>

#define SIZE 5

void test(int *a, int *b, int *c, int size)
{
    int i;
    #pragma omp parallel
    {
        #pragma omp for nowait
        for (i = 0; i < size; i++)
            b[i] = a[i] * a[i];

        #pragma omp for nowait
        for (i = 0; i < size; i++)
            c[i] = a[i]/2;
    }
}

int main( )
{
    int a[SIZE], b[SIZE], c[SIZE];
    int i;

    for (i=0; i<SIZE; i++)
        a[i] = i;

    test(a,b,c, SIZE);

    for (i=0; i<SIZE; i++)
        printf_s("%d, %d, %d\n", a[i], b[i], c[i]);
}
0, 0, 0
1, 1, 0
2, 4, 1
3, 9, 1
4, 16, 2

num_threads

Mengatur jumlah utas dalam tim utas.

num_threads(num)

Parameter

num
Jumlah utas

Keterangan

Klausa num_threads memiliki fungsionalitas yang sama dengan fungsi omp_set_num_threads .

num_threads berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat konstruksi paralel 2.3.

Contoh

Lihat paralel untuk contoh penggunaan num_threads klausa.

dipesan

Diperlukan pada paralel untuk pernyataan jika arahan yang diurutkan akan digunakan dalam perulangan.

ordered

Keterangan

ordered berlaku untuk direktif .

Untuk informasi selengkapnya, lihat 2.4.1 untuk konstruksi.

Contoh

Lihat diurutkan untuk contoh penggunaan ordered klausa.

privat

Menentukan bahwa setiap utas harus memiliki instans variabelnya sendiri.

private(var)

Parameter

var
Variabel untuk memiliki instans di setiap utas.

Keterangan

private berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat 2.7.2.1 privat.

Contoh

// openmp_private.c
// compile with: /openmp
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <omp.h>

#define NUM_THREADS 4
#define SLEEP_THREAD 1
#define NUM_LOOPS 2

enum Types {
   ThreadPrivate,
   Private,
   FirstPrivate,
   LastPrivate,
   Shared,
   MAX_TYPES
};

int nSave[NUM_THREADS][MAX_TYPES][NUM_LOOPS] = {{0}};
int nThreadPrivate;

#pragma omp threadprivate(nThreadPrivate)
#pragma warning(disable:4700)

int main() {
   int nPrivate = NUM_THREADS;
   int nFirstPrivate = NUM_THREADS;
   int nLastPrivate = NUM_THREADS;
   int nShared = NUM_THREADS;
   int nRet = 0;
   int i;
   int j;
   int nLoop = 0;

   nThreadPrivate = NUM_THREADS;
   printf_s("These are the variables before entry "
           "into the parallel region.\n");
   printf_s("nThreadPrivate = %d\n", nThreadPrivate);
   printf_s("      nPrivate = %d\n", nPrivate);
   printf_s(" nFirstPrivate = %d\n", nFirstPrivate);
   printf_s("  nLastPrivate = %d\n", nLastPrivate);
   printf_s("       nShared = %d\n\n", nShared);
   omp_set_num_threads(NUM_THREADS);

   #pragma omp parallel copyin(nThreadPrivate) private(nPrivate) shared(nShared) firstprivate(nFirstPrivate)
   {
      #pragma omp for schedule(static) lastprivate(nLastPrivate)
      for (i = 0 ; i < NUM_THREADS ; ++i) {
         for (j = 0 ; j < NUM_LOOPS ; ++j) {
            int nThread = omp_get_thread_num();
            assert(nThread < NUM_THREADS);

            if (nThread == SLEEP_THREAD)
               Sleep(100);
            nSave[nThread][ThreadPrivate][j] = nThreadPrivate;
            nSave[nThread][Private][j] = nPrivate;
            nSave[nThread][Shared][j] = nShared;
            nSave[nThread][FirstPrivate][j] = nFirstPrivate;
            nSave[nThread][LastPrivate][j] = nLastPrivate;
            nThreadPrivate = nThread;
            nPrivate = nThread;
            nShared = nThread;
            nLastPrivate = nThread;
            --nFirstPrivate;
         }
      }
   }

   for (i = 0 ; i < NUM_LOOPS ; ++i) {
      for (j = 0 ; j < NUM_THREADS ; ++j) {
         printf_s("These are the variables at entry of "
                  "loop %d of thread %d.\n", i + 1, j);
         printf_s("nThreadPrivate = %d\n",
                  nSave[j][ThreadPrivate][i]);
         printf_s("      nPrivate = %d\n",
                  nSave[j][Private][i]);
         printf_s(" nFirstPrivate = %d\n",
                  nSave[j][FirstPrivate][i]);
         printf_s("  nLastPrivate = %d\n",
                  nSave[j][LastPrivate][i]);
         printf_s("       nShared = %d\n\n",
                  nSave[j][Shared][i]);
      }
   }

   printf_s("These are the variables after exit from "
            "the parallel region.\n");
   printf_s("nThreadPrivate = %d (The last value in the "
            "main thread)\n", nThreadPrivate);
   printf_s("      nPrivate = %d (The value prior to "
            "entering parallel region)\n", nPrivate);
   printf_s(" nFirstPrivate = %d (The value prior to "
            "entering parallel region)\n", nFirstPrivate);
   printf_s("  nLastPrivate = %d (The value from the "
            "last iteration of the loop)\n", nLastPrivate);
   printf_s("       nShared = %d (The value assigned, "
            "from the delayed thread, %d)\n\n",
            nShared, SLEEP_THREAD);
}
These are the variables before entry into the parallel region.
nThreadPrivate = 4
      nPrivate = 4
nFirstPrivate = 4
  nLastPrivate = 4
       nShared = 4

These are the variables at entry of loop 1 of thread 0.
nThreadPrivate = 4
      nPrivate = 1310720
nFirstPrivate = 4
  nLastPrivate = 1245104
       nShared = 3

These are the variables at entry of loop 1 of thread 1.
nThreadPrivate = 4
      nPrivate = 4488
nFirstPrivate = 4
  nLastPrivate = 19748
       nShared = 0

These are the variables at entry of loop 1 of thread 2.
nThreadPrivate = 4
      nPrivate = -132514848
nFirstPrivate = 4
  nLastPrivate = -513199792
       nShared = 4

These are the variables at entry of loop 1 of thread 3.
nThreadPrivate = 4
      nPrivate = 1206
nFirstPrivate = 4
  nLastPrivate = 1204
       nShared = 2

These are the variables at entry of loop 2 of thread 0.
nThreadPrivate = 0
      nPrivate = 0
nFirstPrivate = 3
  nLastPrivate = 0
       nShared = 0

These are the variables at entry of loop 2 of thread 1.
nThreadPrivate = 1
      nPrivate = 1
nFirstPrivate = 3
  nLastPrivate = 1
       nShared = 1

These are the variables at entry of loop 2 of thread 2.
nThreadPrivate = 2
      nPrivate = 2
nFirstPrivate = 3
  nLastPrivate = 2
       nShared = 2

These are the variables at entry of loop 2 of thread 3.
nThreadPrivate = 3
      nPrivate = 3
nFirstPrivate = 3
  nLastPrivate = 3
       nShared = 3

These are the variables after exit from the parallel region.
nThreadPrivate = 0 (The last value in the main thread)
      nPrivate = 4 (The value prior to entering parallel region)
nFirstPrivate = 4 (The value prior to entering parallel region)
  nLastPrivate = 3 (The value from the last iteration of the loop)
       nShared = 1 (The value assigned, from the delayed thread, 1)

pengurangan

Menentukan bahwa satu atau beberapa variabel yang bersifat privat untuk setiap utas adalah subjek operasi pengurangan di akhir wilayah paralel.

reduction(operation:var)

Parameter

operasi
Operator untuk operasi yang harus dilakukan pada variabel var di akhir wilayah paralel.

var
Satu atau beberapa variabel untuk melakukan pengurangan skalar. Jika lebih dari satu variabel ditentukan, pisahkan nama variabel dengan koma.

Keterangan

reduction berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat Pengurangan 2.7.2.6.

Contoh

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

#define NUM_THREADS 4
#define SUM_START   1
#define SUM_END     10
#define FUNC_RETS   {1, 1, 1, 1, 1}

int bRets[5] = FUNC_RETS;
int nSumCalc = ((SUM_START + SUM_END) * (SUM_END - SUM_START + 1)) / 2;

int func1( ) {return bRets[0];}
int func2( ) {return bRets[1];}
int func3( ) {return bRets[2];}
int func4( ) {return bRets[3];}
int func5( ) {return bRets[4];}

int main( )
{
    int nRet = 0,
        nCount = 0,
        nSum = 0,
        i,
        bSucceed = 1;

    omp_set_num_threads(NUM_THREADS);

    #pragma omp parallel reduction(+ : nCount)
    {
        nCount += 1;

        #pragma omp for reduction(+ : nSum)
        for (i = SUM_START ; i <= SUM_END ; ++i)
            nSum += i;

        #pragma omp sections reduction(&& : bSucceed)
        {
            #pragma omp section
            {
                bSucceed = bSucceed && func1( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func2( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func3( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func4( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func5( );
            }
        }
    }

    printf_s("The parallel section was executed %d times "
             "in parallel.\n", nCount);
    printf_s("The sum of the consecutive integers from "
             "%d to %d, is %d\n", 1, 10, nSum);

    if (bSucceed)
        printf_s("All of the functions, func1 through "
                 "func5 succeeded!\n");
    else
        printf_s("One or more of the functions, func1 "
                 "through func5 failed!\n");

    if (nCount != NUM_THREADS)
    {
        printf_s("ERROR: For %d threads, %d were counted!\n",
                 NUM_THREADS, nCount);
        nRet |= 0x1;
   }

    if (nSum != nSumCalc)
    {
        printf_s("ERROR: The sum of %d through %d should be %d, "
                "but %d was reported!\n",
                SUM_START, SUM_END, nSumCalc, nSum);
        nRet |= 0x10;
    }

    if (bSucceed != (bRets[0] && bRets[1] &&
                     bRets[2] && bRets[3] && bRets[4]))
    {
        printf_s("ERROR: The sum of %d through %d should be %d, "
                 "but %d was reported!\n",
                 SUM_START, SUM_END, nSumCalc, nSum);
        nRet |= 0x100;
    }
}
The parallel section was executed 4 times in parallel.
The sum of the consecutive integers from 1 to 10, is 55
All of the functions, func1 through func5 succeeded!

jadwal

Berlaku untuk direktif .

schedule(type[,size])

Parameter

jenis
Jenis penjadwalan, baik dynamic, , guidedruntime, atau static.

ukuran
(Opsional) Menentukan ukuran iterasi. ukuran harus berupa bilangan bulat. Tidak valid ketika jenis adalah runtime.

Keterangan

Untuk informasi selengkapnya, lihat 2.4.1 untuk konstruksi.

Contoh

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

#define NUM_THREADS 4
#define STATIC_CHUNK 5
#define DYNAMIC_CHUNK 5
#define NUM_LOOPS 20
#define SLEEP_EVERY_N 3

int main( )
{
    int nStatic1[NUM_LOOPS],
        nStaticN[NUM_LOOPS];
    int nDynamic1[NUM_LOOPS],
        nDynamicN[NUM_LOOPS];
    int nGuided[NUM_LOOPS];

    omp_set_num_threads(NUM_THREADS);

    #pragma omp parallel
    {
        #pragma omp for schedule(static, 1)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nStatic1[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(static, STATIC_CHUNK)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nStaticN[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(dynamic, 1)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nDynamic1[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(dynamic, DYNAMIC_CHUNK)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nDynamicN[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(guided)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nGuided[i] = omp_get_thread_num( );
        }
    }

    printf_s("------------------------------------------------\n");
    printf_s("| static | static | dynamic | dynamic | guided |\n");
    printf_s("|    1   |    %d   |    1    |    %d    |        |\n",
             STATIC_CHUNK, DYNAMIC_CHUNK);
    printf_s("------------------------------------------------\n");

    for (int i=0; i<NUM_LOOPS; ++i)
    {
        printf_s("|    %d   |    %d   |    %d    |    %d    |"
                 "    %d   |\n",
                 nStatic1[i], nStaticN[i],
                 nDynamic1[i], nDynamicN[i], nGuided[i]);
    }

    printf_s("------------------------------------------------\n");
}
------------------------------------------------
| static | static | dynamic | dynamic | guided |
|    1   |    5   |    1    |    5    |        |
------------------------------------------------
|    0   |    0   |    0    |    2    |    1   |
|    1   |    0   |    3    |    2    |    1   |
|    2   |    0   |    3    |    2    |    1   |
|    3   |    0   |    3    |    2    |    1   |
|    0   |    0   |    2    |    2    |    1   |
|    1   |    1   |    2    |    3    |    3   |
|    2   |    1   |    2    |    3    |    3   |
|    3   |    1   |    0    |    3    |    3   |
|    0   |    1   |    0    |    3    |    3   |
|    1   |    1   |    0    |    3    |    2   |
|    2   |    2   |    1    |    0    |    2   |
|    3   |    2   |    1    |    0    |    2   |
|    0   |    2   |    1    |    0    |    3   |
|    1   |    2   |    2    |    0    |    3   |
|    2   |    2   |    2    |    0    |    0   |
|    3   |    3   |    2    |    1    |    0   |
|    0   |    3   |    3    |    1    |    1   |
|    1   |    3   |    3    |    1    |    1   |
|    2   |    3   |    3    |    1    |    1   |
|    3   |    3   |    0    |    1    |    3   |
------------------------------------------------

dibagikan

Menentukan bahwa satu atau beberapa variabel harus dibagikan di antara semua utas.

shared(var)

Parameter

var
Satu atau beberapa variabel untuk dibagikan. Jika lebih dari satu variabel ditentukan, pisahkan nama variabel dengan koma.

Keterangan

Cara lain untuk berbagi variabel di antara utas adalah dengan klausul copyprivate .

shared berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat berbagi 2.7.2.4.

Contoh

Lihat privat untuk contoh penggunaan shared.