Bagikan melalui


Klausul OpenMP

Menyediakan tautan ke klausul yang digunakan dalam OPENMP API.

Visual C++ mendukung klausul OpenMP berikut.

Untuk atribut umum:

Klausul Deskripsi
jika Menentukan apakah perulangan harus dijalankan secara paralel atau dalam serial.
num_threads Mengatur jumlah utas dalam tim utas.
Memerintahkan Diperlukan pada pernyataan paralel untuk jika arahan diurutkan akan digunakan dalam perulangan.
jadwal Berlaku untuk direktif for.
nowait Mengabaikan pembatas yang implisit dalam sebuah 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).
dibagikan Menentukan bahwa satu atau beberapa variabel harus dibagikan di antara semua utas.
Default Menentukan perilaku variabel tanpa cakupan dalam wilayah paralel.
Pengurangan Menentukan bahwa satu atau lebih variabel yang bersifat pribadi untuk setiap utas adalah subjek dari sebuah operasi reduksi di akhir bagian paralel.
copyin Memungkinkan utas untuk mengakses nilai dari utas utama, untuk variabel threadprivate.
copyprivate Menentukan bahwa satu atau beberapa variabel harus dibagi di antara semua thread.

copyin

Memungkinkan thread untuk mengakses nilai dari thread utama, untuk variabel threadprivate.

copyin(var)

Parameter

var
Variabel threadprivate yang akan diinisialisasi dengan nilai variabelnya di utas utama, sebagaimana adanya sebelum konstruksi paralel.

Keterangan

copyin berlaku untuk arahan berikut:

Untuk informasi selengkapnya, lihat 2.7.2.7 copyin.

Contoh

Lihat threadprivate untuk contoh penggunaan copyin.

copyprivate

Menentukan bahwa satu atau beberapa variabel harus dibagi di antara semua thread.

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

asali

Menentukan perilaku variabel tanpa cakupan dalam 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 instance di setiap thread dan akan diinisialisasi dengan nilai variabel tersebut, karena sudah 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 dievaluasi menjadi false (nol), wilayah paralel dijalankan secara sekuensial (oleh 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

Mengabaikan pembatas yang implisit dalam sebuah arahan.

nowait

Keterangan

nowait berlaku untuk arahan berikut:

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

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

jumlah_utas

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.

diurutkan

Diperlukan pada pernyataan paralel untuk jika arahan 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 yang 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 lebih variabel yang bersifat pribadi untuk setiap utas adalah subjek dari sebuah operasi reduksi di akhir bagian 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 for.

schedule(type[,size])

Parameter

jenis
Jenis penjadwalan, apakah dynamic, guided, runtime, 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 dibagi di antara semua thread.

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 klausa copyprivate.

shared berlaku untuk arahan berikut:

Untuk informasi lebih lanjut, lihat 2.7.2.4 shared.

Contoh

Lihat privat untuk contoh penggunaan shared.