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
, , 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 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
.
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk