Bagikan melalui


2. Arahan

Arahan didasarkan pada #pragma arahan yang ditentukan dalam standar C dan C++. Pengkompilasi yang mendukung OPENMP C dan C++ API akan menyertakan opsi baris perintah yang mengaktifkan dan memungkinkan interpretasi semua arahan kompilator OpenMP.

2.1 Format arahan

Sintaksis arahan OpenMP secara resmi ditentukan oleh tata bahasa dalam lampiran C, dan secara informal sebagai berikut:

#pragma omp directive-name  [clause[ [,] clause]...] new-line

Setiap arahan dimulai dengan #pragma omp, untuk mengurangi potensi konflik dengan arahan pragma lain (non-OpenMP atau ekstensi vendor ke OpenMP) dengan nama yang sama. Arahan lainnya mengikuti konvensi standar C dan C++ untuk arahan kompilator. Secara khusus, spasi kosong dapat digunakan sebelum dan sesudah #, dan terkadang spasi kosong harus digunakan untuk memisahkan kata-kata dalam arahan. Token praproses mengikuti #pragma omp tunduk pada penggantian makro.

Arahan peka huruf besar/kecil. Urutan di mana klausul muncul dalam arahan tidak signifikan. Klausul tentang arahan dapat diulang sesuai kebutuhan, tunduk pada batasan yang tercantum dalam deskripsi setiap klausa. Jika daftar variabel muncul dalam klausul, itu hanya harus menentukan variabel. Hanya satu nama direktif yang dapat ditentukan per direktif. Misalnya, arahan berikut tidak diizinkan:

/* ERROR - multiple directive names not allowed */
#pragma omp parallel barrier

Arahan OpenMP berlaku untuk paling banyak satu pernyataan yang berhasil, yang harus merupakan blok terstruktur.

2.2 Kompilasi bersyar

Nama _OPENMP makro didefinisikan oleh implementasi yang mematuhi OpenMP sebagai konstanta desimal yyyymm, yang akan menjadi tahun dan bulan dari spesifikasi yang disetujui. Makro ini tidak boleh menjadi subjek direktif #define praproses atau #undef praproses.

#ifdef _OPENMP
iam = omp_get_thread_num() + index;
#endif

Jika vendor menentukan ekstensi ke OpenMP, mereka dapat menentukan makro tambahan yang telah ditentukan sebelumnya.

2.3 Konstruksi paralel

Direktif berikut mendefinisikan wilayah paralel, yang merupakan wilayah program yang akan dijalankan oleh banyak utas secara paralel. Arahan ini adalah konstruksi mendasar yang memulai eksekusi paralel.

#pragma omp parallel [clause[ [, ]clause] ...] new-line   structured-block

Klausanya adalah salah satu hal berikut:

  • if(ekspresi skalar )
  • private(daftar variabel )
  • firstprivate(daftar variabel )
  • default(shared | none)
  • shared(daftar variabel )
  • copyin(daftar variabel )
  • reduction(Operator :daftar variabel )
  • num_threads(ekspresi bilangan bulat )

Ketika utas sampai ke konstruksi paralel, tim utas dibuat jika salah satu kasus berikut ini benar:

  • Tidak ada if klausa yang ada.
  • Ekspresi if mengevaluasi ke nilai bukan nol.

Utas ini menjadi utas master tim, dengan utas berjumlah 0, dan semua utas dalam tim, termasuk utas master, menjalankan wilayah secara paralel. Jika nilai if ekspresi adalah nol, wilayah diserialisasikan.

Untuk menentukan jumlah utas yang diminta, aturan berikut akan dipertimbangkan secara berurutan. Aturan pertama yang kondisinya terpenuhi akan diterapkan:

  1. num_threads Jika klausa ada, maka nilai ekspresi bilangan bulat adalah jumlah utas yang diminta.

  2. omp_set_num_threads Jika fungsi pustaka telah dipanggil, maka nilai argumen dalam panggilan yang terakhir dijalankan adalah jumlah utas yang diminta.

  3. Jika variabel OMP_NUM_THREADS lingkungan ditentukan, maka nilai variabel lingkungan ini adalah jumlah utas yang diminta.

  4. Jika tidak ada metode di atas yang digunakan, maka jumlah utas yang diminta ditentukan implementasi.

num_threads Jika klausul ada maka menggantikan jumlah utas yang diminta oleh omp_set_num_threads fungsi pustaka atau OMP_NUM_THREADS variabel lingkungan hanya untuk wilayah paralel yang diterapkannya. Wilayah paralel nanti tidak terpengaruh olehnya.

Jumlah utas yang menjalankan wilayah paralel juga bergantung pada apakah penyesuaian dinamis jumlah utas diaktifkan. Jika penyesuaian dinamis dinonaktifkan, maka jumlah utas yang diminta akan menjalankan wilayah paralel. Jika penyesuaian dinamis diaktifkan, jumlah utas yang diminta adalah jumlah maksimum utas yang dapat menjalankan wilayah paralel.

Jika wilayah paralel ditemui sementara penyesuaian dinamis jumlah utas dinonaktifkan, dan jumlah utas yang diminta untuk wilayah paralel lebih dari jumlah yang dapat disediakan sistem run-time, perilaku program ditentukan implementasi. Implementasi dapat, misalnya, mengganggu eksekusi program, atau dapat menserialisasikan wilayah paralel.

Fungsi omp_set_dynamic pustaka dan OMP_DYNAMIC variabel lingkungan dapat digunakan untuk mengaktifkan dan menonaktifkan penyesuaian dinamis jumlah utas.

Jumlah prosesor fisik yang benar-benar menghosting utas pada waktu tertentu ditentukan implementasi. Setelah dibuat, jumlah utas dalam tim tetap konstan selama durasi wilayah paralel tersebut. Ini dapat diubah baik secara eksplisit oleh pengguna atau secara otomatis oleh sistem run-time dari satu wilayah paralel ke wilayah lainnya.

Pernyataan yang terkandung dalam tingkat dinamis wilayah paralel dijalankan oleh setiap utas, dan setiap utas dapat menjalankan jalur pernyataan yang berbeda dari utas lainnya. Arahan yang ditemui di luar tingkat leksikal wilayah paralel disebut sebagai arahan yatim piatu.

Ada penghambat tersirat di akhir wilayah paralel. Hanya utas master tim yang melanjutkan eksekusi di akhir wilayah paralel.

Jika utas dalam tim yang menjalankan wilayah paralel mengalami konstruksi paralel lain, itu membuat tim baru, dan itu menjadi master tim baru tersebut. Wilayah paralel berlapis diserialisasikan secara default. Akibatnya, secara default, wilayah paralel berlapis dijalankan oleh tim yang terdiri dari satu utas. Perilaku default dapat diubah dengan menggunakan fungsi omp_set_nested pustaka runtime atau variabel OMP_NESTEDlingkungan . Namun, jumlah utas dalam tim yang menjalankan wilayah paralel berlapis ditentukan implementasi.

Pembatasan arahan parallel adalah sebagai berikut:

  • Paling banyak, satu if klausa dapat muncul di arahan.

  • Ini tidak ditentukan apakah ada efek samping di dalam ekspresi atau num_threads ekspresi jika terjadi.

  • Dijalankan throw di dalam wilayah paralel harus menyebabkan eksekusi dilanjutkan dalam jangkauan dinamis dari blok terstruktur yang sama, dan harus ditangkap oleh utas yang sama yang melemparkan pengecualian.

  • Hanya satu num_threads klausa yang dapat muncul di direktif. Ekspresi num_threads dievaluasi di luar konteks wilayah paralel, dan harus dievaluasi ke nilai bilangan bulat positif.

  • Urutan evaluasi if klausa dan num_threads tidak ditentukan.

Referensi silang

  • private, firstprivate, default, shared, copyin, dan reduction klausul (bagian 2.7.2)
  • variabel lingkungan OMP_NUM_THREADS
  • omp_set_dynamic fungsi pustaka
  • variabel lingkungan OMP_DYNAMIC
  • fungsi omp_set_nested
  • variabel lingkungan OMP_NESTED
  • omp_set_num_threads fungsi pustaka

2.4 Konstruksi berbagi kerja

Konstruksi berbagi kerja mendistribusikan eksekusi pernyataan terkait di antara anggota tim yang menemukannya. Arahan berbagi kerja tidak meluncurkan utas baru, dan tidak ada hambatan tersirat tentang entri ke konstruksi berbagi kerja.

Urutan konstruksi dan barrier arahan berbagi kerja yang ditemui harus sama untuk setiap utas dalam tim.

OpenMP mendefinisikan konstruksi berbagi kerja berikut, dan konstruksi ini dijelaskan di bagian berikut:

2.4.1 untuk konstruksi

Direktif for mengidentifikasi konstruksi berbagi kerja berulang yang menentukan bahwa iterasi perulangan terkait akan dijalankan secara paralel. Iterasi perulangan didistribusikan for di seluruh utas yang sudah ada di tim yang menjalankan konstruksi paralel yang mengikatnya. Sintaks konstruksi for adalah sebagai berikut:

#pragma omp for [clause[[,] clause] ... ] new-line for-loop

Klausanya adalah salah satu hal berikut:

  • private(daftar variabel )
  • firstprivate(daftar variabel )
  • lastprivate(daftar variabel )
  • reduction(Operator : daftar variabel )
  • ordered
  • schedule(kind [, chunk_size ])
  • nowait

Direktif for menempatkan pembatasan pada struktur perulangan yang for sesuai. Secara khusus, perulangan yang for sesuai harus memiliki bentuk kanonis:

for (init-expr ; var logical-op b ; incr-expr )

init-expr
Salah satu dari berikut ini:

  • var = lb
  • integer-type var = lb

incr-expr
Salah satu dari berikut ini:

  • ++Var
  • Var ++
  • --Var
  • Var --
  • var += incr
  • var -= incr
  • var = var + incr
  • var = incr + var
  • var = var - incr

var
Variabel bilangan bulat yang ditandatangani. Jika variabel ini akan dibagikan, variabel ini secara implisit dibuat privat selama durasi for. Jangan ubah variabel ini dalam isi for pernyataan. Kecuali variabel ditentukan lastprivate, nilainya setelah perulangan tidak ditentukan.

logical-op
Salah satu dari berikut ini:

  • <
  • <=
  • >
  • >=

lb, b, dan incr
Mengulang ekspresi bilangan bulat invariant. Tidak ada sinkronisasi selama evaluasi ekspresi ini, sehingga efek samping yang dievaluasi menghasilkan hasil yang tidak ditentukan.

Bentuk kanonis memungkinkan jumlah iterasi perulangan untuk dihitung pada entri ke perulangan. Komputasi ini dibuat dengan nilai dalam jenis var, setelah promosi integral. Secara khusus, jika nilai b - lb + incr tidak dapat diwakili dalam jenis tersebut, hasilnya tidak ditentukan. Selanjutnya, jika logical-op adalah < atau <=, maka incr-expr harus menyebabkan var meningkat pada setiap perulangan perulangan. Jika logical-op adalah > atau >=, maka incr-expr harus menyebabkan var menjadi lebih kecil pada setiap iterasi perulangan.

Klausa schedule menentukan bagaimana iterasi for perulangan dibagi di antara utas tim. Kebenaran program tidak boleh bergantung pada utas mana yang menjalankan iterasi tertentu. Nilai chunk_size, jika ditentukan, harus berupa ekspresi bilangan bulat invarian perulangan dengan nilai positif. Tidak ada sinkronisasi selama evaluasi ekspresi ini, sehingga efek samping yang dievaluasi menghasilkan hasil yang tidak ditentukan. Jenis jadwal bisa menjadi salah satu nilai berikut:

Tabel 2-1: schedule nilai jenis klausa

Nilai Deskripsi
statik Ketika schedule(static, chunk_size ) ditentukan, iterasi dibagi menjadi potongan ukuran yang ditentukan oleh chunk_size. Gugus secara statis ditetapkan ke utas dalam tim dengan cara round-robin dalam urutan nomor utas. Ketika tidak ada chunk_size yang ditentukan, ruang iterasi dibagi menjadi potongan yang berukuran kira-kira sama, dengan satu gugus yang ditetapkan ke setiap utas.
dinamis Ketika schedule(dynamic, chunk_size ) ditentukan, iterasi dibagi menjadi serangkaian gugus, masing-masing berisi chunk_size iterasi. Setiap gugus ditetapkan ke utas yang menunggu tugas. Utas menjalankan potongan iterasi dan kemudian menunggu tugas berikutnya, sampai tidak ada gugus yang tetap ditetapkan. Potongan terakhir yang akan ditetapkan mungkin memiliki jumlah iterasi yang lebih kecil. Ketika tidak ada chunk_size yang ditentukan, chunk_size default ke 1.
Dipandu Ketika schedule(guided, chunk_size ) ditentukan, iterasi ditetapkan ke utas dalam gugus dengan ukuran yang menurun. Ketika utas menyelesaikan potongan iterasi yang ditetapkan, utas tersebut secara dinamis diberi potongan lain, sampai tidak ada yang tersisa. Untuk chunk_size 1, ukuran setiap gugus kira-kira jumlah iterasi yang tidak ditetapkan dibagi dengan jumlah utas. Ukuran ini berkurang hampir eksponensial menjadi 1. Untuk chunk_size dengan nilai k lebih besar dari 1, ukuran berkurang hampir eksponensial ke k, kecuali bahwa gugus terakhir mungkin memiliki kurang dari perulangan k. Ketika tidak ada chunk_size yang ditentukan, chunk_size default ke 1.
runtime Ketika schedule(runtime) ditentukan, keputusan mengenai penjadwalan ditangguhkan hingga runtime. Jenis jadwal dan ukuran gugus dapat dipilih pada waktu proses dengan mengatur variabel OMP_SCHEDULElingkungan . Jika variabel lingkungan ini tidak diatur, jadwal yang dihasilkan ditentukan implementasi. Ketika schedule(runtime) ditentukan, chunk_size tidak boleh ditentukan.

Dengan tidak adanya klausul yang ditentukan schedule secara eksplisit, defaultnya schedule ditentukan implementasi.

Program yang mematuhi OpenMP tidak boleh mengandalkan jadwal tertentu untuk eksekusi yang benar. Program tidak boleh mengandalkan jenis jadwal yang sesuai dengan deskripsi yang diberikan di atas, karena dimungkinkan untuk memiliki variasi dalam implementasi jenis jadwal yang sama di berbagai kompilator. Deskripsi dapat digunakan untuk memilih jadwal yang sesuai untuk situasi tertentu.

Klausul ordered harus ada ketika ordered direktif mengikat for konstruksi.

Ada hambatan implisit di akhir for konstruksi kecuali nowait klausul ditentukan.

Pembatasan arahan for adalah sebagai berikut:

  • Perulangan for harus merupakan blok terstruktur, dan, selain itu, eksekusinya tidak boleh dihentikan oleh break pernyataan.

  • Nilai ekspresi kontrol perulangan dari for perulangan yang for terkait dengan direktif harus sama untuk semua utas dalam tim.

  • Variabel for iterasi perulangan harus memiliki jenis bilangan bulat yang ditandatangani.

  • Hanya satu schedule klausa yang dapat muncul pada arahan for .

  • Hanya satu ordered klausa yang dapat muncul pada arahan for .

  • Hanya satu nowait klausa yang dapat muncul pada arahan for .

  • Ini tidak ditentukan jika atau seberapa sering efek samping dalam ekspresi chunk_size, lb, b, atau incr terjadi.

  • Nilai ekspresi chunk_size harus sama untuk semua utas dalam tim.

Referensi silang

2.4.2 konstruksi bagian

Direktif sections mengidentifikasi konstruksi berbagi kerja noniteratif yang menentukan serangkaian konstruksi yang akan dibagi di antara utas dalam tim. Setiap bagian dijalankan sekali oleh utas dalam tim. Sintaks sections direktif adalah sebagai berikut:

#pragma omp sections [clause[[,] clause] ...] new-line
   {
   [#pragma omp section new-line]
      structured-block
   [#pragma omp section new-linestructured-block ]
...
}

Klausanya adalah salah satu hal berikut:

  • private(daftar variabel )
  • firstprivate(daftar variabel )
  • lastprivate(daftar variabel )
  • reduction(Operator :daftar variabel )
  • nowait

Setiap bagian didahului oleh section arahan, meskipun arahan section bersifat opsional untuk bagian pertama. Arahan section harus muncul dalam jangkauan leksikal arahan sections . Ada hambatan implisit di akhir sections konstruksi, kecuali nowait ditentukan.

Pembatasan arahan sections adalah sebagai berikut:

  • Arahan section tidak boleh muncul di luar tingkat leksikal direktif sections .

  • Hanya satu nowait klausa yang dapat muncul pada arahan sections .

Referensi silang

  • private, firstprivate, lastprivate, dan reduction klausa (bagian 2.7.2)

2.4.3 konstruksi tunggal

Direktif single mengidentifikasi konstruksi yang menentukan bahwa blok terstruktur terkait hanya dijalankan oleh satu utas dalam tim (belum tentu utas master). Sintaks single direktif adalah sebagai berikut:

#pragma omp single [clause[[,] clause] ...] new-linestructured-block

Klausanya adalah salah satu hal berikut:

  • private(daftar variabel )
  • firstprivate(daftar variabel )
  • copyprivate(daftar variabel )
  • nowait

Ada hambatan implisit setelah single konstruksi kecuali nowait klausul ditentukan.

Pembatasan arahan single adalah sebagai berikut:

  • Hanya satu nowait klausa yang dapat muncul pada arahan single .
  • Klausa copyprivate tidak boleh digunakan dengan nowait klausul .

Referensi silang

  • private, firstprivate, dan copyprivate klausa (bagian 2.7.2)

2.5 Gabungan konstruksi berbagi kerja paralel

Konstruksi berbagi kerja paralel gabungan adalah pintasan untuk menentukan wilayah paralel yang hanya memiliki satu konstruksi berbagi kerja. Semantik arahan ini sama dengan menentukan direktif secara parallel eksplisit diikuti oleh satu konstruksi berbagi kerja.

Bagian berikut menjelaskan konstruksi berbagi kerja paralel gabungan:

2.5.1 paralel untuk konstruksi

Direktif parallel for adalah pintasan untuk parallel wilayah yang hanya berisi satu for arahan. Sintaks parallel for direktif adalah sebagai berikut:

#pragma omp parallel for [clause[[,] clause] ...] new-linefor-loop

Arahan ini memungkinkan semua klausul parallel direktif dan for arahan, kecuali nowait klausul, dengan arti dan batasan yang identik. Semantik sama dengan secara eksplisit menentukan arahan parallel segera diikuti oleh for arahan.

Referensi silang

2.5.2 konstruksi bagian paralel

Direktif parallel sections menyediakan formulir pintasan untuk menentukan parallel wilayah yang hanya memiliki satu sections arahan. Semantik sama dengan secara eksplisit menentukan arahan parallel segera diikuti oleh sections arahan. Sintaks parallel sections direktif adalah sebagai berikut:

#pragma omp parallel sections  [clause[[,] clause] ...] new-line
   {
   [#pragma omp section new-line]
      structured-block
   [#pragma omp section new-linestructured-block  ]
   ...
}

Klausa dapat menjadi salah satu klausul yang diterima oleh arahan parallel dan sections , kecuali nowait klausul .

Referensi silang

2.6 Arahan master dan sinkronisasi

Bagian berikut ini menjelaskan:

2.6.1 konstruksi master

Direktif master mengidentifikasi konstruksi yang menentukan blok terstruktur yang dijalankan oleh utas master tim. Sintaks master direktif adalah sebagai berikut:

#pragma omp master new-linestructured-block

Utas lain dalam tim tidak menjalankan blok terstruktur terkait. Tidak ada penghalang tersirat baik saat masuk atau keluar dari konstruksi master.

2.6.2 konstruksi kritis

Direktif critical mengidentifikasi konstruksi yang membatasi eksekusi blok terstruktur terkait ke satu utas pada satu waktu. Sintaks critical direktif adalah sebagai berikut:

#pragma omp critical [(name)]  new-linestructured-block

Nama opsional dapat digunakan untuk mengidentifikasi wilayah penting. Pengidentifikasi yang digunakan untuk mengidentifikasi wilayah penting memiliki tautan eksternal dan berada di ruang nama yang terpisah dari spasi nama yang digunakan oleh label, tag, anggota, dan pengidentifikasi biasa.

Utas menunggu di awal wilayah penting sampai tidak ada utas lain yang menjalankan wilayah penting (di mana saja dalam program) dengan nama yang sama. Semua direktif yang tidak disebutkan critical namanya memetakan ke nama yang tidak ditentukan yang sama.

2.6.3 direktif hambatan

Direktif barrier menyinkronkan semua utas dalam tim. Ketika ditemui, setiap utas dalam tim menunggu sampai semua yang lain mencapai titik ini. Sintaks barrier direktif adalah sebagai berikut:

#pragma omp barrier new-line

Setelah semua utas dalam tim mengalami hambatan, setiap utas dalam tim mulai menjalankan pernyataan setelah direktif hambatan secara paralel. Karena direktif barrier tidak memiliki pernyataan bahasa C sebagai bagian dari sintaksnya, ada beberapa batasan pada penempatannya dalam suatu program. Untuk informasi selengkapnya tentang tata bahasa formal, lihat lampiran C. Contoh di bawah ini menggambarkan pembatasan ini.

/* ERROR - The barrier directive cannot be the immediate
*          substatement of an if statement
*/
if (x!=0)
   #pragma omp barrier
...

/* OK - The barrier directive is enclosed in a
*      compound statement.
*/
if (x!=0) {
   #pragma omp barrier
}

2.6.4 konstruksi atom

Direktif atomic memastikan bahwa lokasi memori tertentu diperbarui secara atomik, daripada mengeksposnya ke kemungkinan beberapa utas penulisan simultan. Sintaks atomic direktif adalah sebagai berikut:

#pragma omp atomic new-lineexpression-stmt

Pernyataan ekspresi harus memiliki salah satu formulir berikut:

  • x binop = expr
  • x ++
  • ++x
  • x --
  • --x

Dalam ekspresi sebelumnya:

  • x adalah ekspresi lvalue dengan jenis skalar.

  • expr adalah ekspresi dengan jenis skalar , dan tidak mereferensikan objek yang ditunjuk oleh x.

  • binop bukan operator yang kelebihan beban dan merupakan salah satu dari +, , *, -/, &, ^, |, <<, atau >>.

Meskipun didefinisikan implementasi apakah implementasi menggantikan semua atomic arahan dengan critical arahan yang memiliki nama unik yang sama, arahan atomic mengizinkan pengoptimalan yang lebih baik. Seringkali instruksi perangkat keras tersedia yang dapat melakukan pembaruan atom dengan overhead paling sedikit.

Hanya beban dan penyimpanan objek yang ditunjuk oleh x yang atom; evaluasi expr tidak atomik. Untuk menghindari kondisi balapan, semua pembaruan lokasi secara paralel harus dilindungi dengan atomic arahan, kecuali yang diketahui bebas dari kondisi balapan.

Pembatasan arahan atomic adalah sebagai berikut:

  • Semua referensi atom ke lokasi penyimpanan x di seluruh program diperlukan untuk memiliki jenis yang kompatibel.

Contoh

extern float a[], *p = a, b;
/* Protect against races among multiple updates. */
#pragma omp atomic
a[index[i]] += b;
/* Protect against races with updates through a. */
#pragma omp atomic
p[i] -= 1.0f;

extern union {int n; float x;} u;
/* ERROR - References through incompatible types. */
#pragma omp atomic
u.n++;
#pragma omp atomic
u.x -= 1.0f;

2.6.5 direktif flush

Direktif flush , baik eksplisit atau tersirat, menentukan titik urutan "lintas alur" di mana implementasi diperlukan untuk memastikan bahwa semua utas dalam tim memiliki tampilan objek tertentu yang konsisten (ditentukan di bawah) dalam memori. Ini berarti bahwa evaluasi ekspresi sebelumnya yang mereferensikan objek tersebut selesai dan evaluasi berikutnya belum dimulai. Misalnya, kompilator harus memulihkan nilai objek dari register ke memori, dan perangkat keras mungkin perlu menghapus buffer tulis ke memori dan memuat ulang nilai objek dari memori.

Sintaks flush direktif adalah sebagai berikut:

#pragma omp flush [(variable-list)]  new-line

Jika objek yang memerlukan sinkronisasi semuanya dapat ditunjuk oleh variabel, maka variabel tersebut dapat ditentukan dalam daftar variabel opsional. Jika penunjuk ada dalam daftar variabel, penunjuk itu sendiri dibersihkan, bukan objek yang dirujuk penunjuk.

Direktif flush tanpa daftar variabel menyinkronkan semua objek bersama kecuali objek yang tidak dapat diakses dengan durasi penyimpanan otomatis. (Ini kemungkinan memiliki lebih banyak overhead daripada flush dengan daftar variabel.) Direktif flush tanpa daftar variabel tersirat untuk arahan berikut:

  • barrier
  • Pada entri ke dan keluar dari critical
  • Pada entri ke dan keluar dari ordered
  • Pada entri ke dan keluar dari parallel
  • Saat keluar dari for
  • Saat keluar dari sections
  • Saat keluar dari single
  • Pada entri ke dan keluar dari parallel for
  • Pada entri ke dan keluar dari parallel sections

Direktif tidak tersirat jika ada nowait klausul. Perlu dicatat bahwa arahan flush tidak tersirat untuk salah satu hal berikut:

  • Pada entri ke for
  • Pada entri ke atau keluar dari master
  • Pada entri ke sections
  • Pada entri ke single

Referensi yang mengakses nilai objek dengan jenis yang memenuhi syarat volatil bersifat seolah-olah flush ada arahan yang menentukan objek tersebut pada titik urutan sebelumnya. Referensi yang memodifikasi nilai objek dengan jenis yang memenuhi syarat volatil bersifat seolah-olah flush ada arahan yang menentukan objek tersebut pada titik urutan berikutnya.

Karena direktif flush tidak memiliki pernyataan bahasa C sebagai bagian dari sintaksnya, ada beberapa batasan pada penempatannya dalam suatu program. Untuk informasi selengkapnya tentang tata bahasa formal, lihat lampiran C. Contoh di bawah ini menggambarkan pembatasan ini.

/* ERROR - The flush directive cannot be the immediate
*          substatement of an if statement.
*/
if (x!=0)
   #pragma omp flush (x)
...

/* OK - The flush directive is enclosed in a
*      compound statement
*/
if (x!=0) {
   #pragma omp flush (x)
}

Pembatasan arahan flush adalah sebagai berikut:

  • Variabel yang ditentukan dalam flush direktif tidak boleh memiliki jenis referensi.

2.6.6 konstruksi yang diurutkan

Blok terstruktur setelah arahan ordered dijalankan dalam urutan di mana iterasi akan dijalankan dalam perulangan berurutan. Sintaks ordered direktif adalah sebagai berikut:

#pragma omp ordered new-linestructured-block

Arahan ordered harus berada dalam tingkat dinamis dari suatu for atau parallel for konstruksi. for Atau parallel for direktif tempat ordered pengikatan konstruksi harus memiliki klausa yang ordered ditentukan seperti yang dijelaskan dalam bagian 2.4.1. Dalam eksekusi for atau parallel for konstruksi dengan ordered klausul, ordered konstruksi dijalankan secara ketat dalam urutan di mana mereka akan dijalankan dalam eksekusi berurutan dari perulangan.

Pembatasan arahan ordered adalah sebagai berikut:

  • Iterasi perulangan dengan for konstruksi tidak boleh menjalankan direktif yang diurutkan yang sama lebih dari sekali, dan tidak boleh menjalankan lebih dari satu ordered arahan.

2.7 Lingkungan data

Bagian ini menyajikan direktif dan beberapa klausa untuk mengontrol lingkungan data selama eksekusi wilayah paralel, sebagai berikut:

  • Direktif threadprivate disediakan untuk membuat cakupan file, cakupan namespace, atau variabel cakupan blok statis lokal ke utas.

  • Klausul yang dapat ditentukan pada arahan untuk mengontrol atribut berbagi variabel selama durasi konstruksi paralel atau berbagi kerja dijelaskan dalam bagian 2.7.2.

2.7.1 direktif threadprivate

Direktif threadprivate membuat variabel cakupan file bernama, namespace-scope, atau block-scope statis yang ditentukan dalam variabel-list privat ke utas. variabel-list adalah daftar variabel yang dipisahkan koma yang tidak memiliki jenis yang tidak lengkap. Sintaks threadprivate direktif adalah sebagai berikut:

#pragma omp threadprivate(variable-list) new-line

Setiap salinan threadprivate variabel diinisialisasi sekali, pada titik yang tidak ditentukan dalam program sebelum referensi pertama ke salinan tersebut, dan dengan cara yang biasa (yaitu, karena salinan master akan diinisialisasi dalam eksekusi serial program). Perhatikan bahwa jika objek dirujuk dalam penginisialisasi threadprivate eksplisit variabel, dan nilai objek dimodifikasi sebelum referensi pertama ke salinan variabel, maka perilaku tidak ditentukan.

Seperti halnya variabel privat apa pun, utas tidak boleh mereferensikan salinan threadprivate objek utas lain. Selama wilayah serial dan wilayah master program, referensi akan menjadi salinan objek utas master.

Setelah wilayah paralel pertama dijalankan, data dalam objek dijamin threadprivate akan bertahan hanya jika mekanisme utas dinamis telah dinonaktifkan dan jika jumlah utas tetap tidak berubah untuk semua wilayah paralel.

Pembatasan arahan threadprivate adalah sebagai berikut:

  • threadprivate Direktif untuk cakupan file atau variabel cakupan namespace harus muncul di luar definisi atau deklarasi apa pun, dan harus secara leksikal mendahului semua referensi ke salah satu variabel dalam daftarnya.

  • Setiap variabel dalam daftar threadprivate variabel direktif pada cakupan file atau namespace harus merujuk ke deklarasi variabel pada cakupan file atau namespace yang secara leksikal mendahului arahan.

  • threadprivate Direktif untuk variabel cakupan blok statis harus muncul dalam cakupan variabel dan bukan dalam cakupan berlapis. Direktif harus secara leksikal mendahului semua referensi ke salah satu variabel dalam daftarnya.

  • Setiap variabel dalam daftar variabel arahan threadprivate dalam cakupan blok harus merujuk ke deklarasi variabel dalam cakupan yang sama yang secara leksikal mendahului arahan. Deklarasi variabel harus menggunakan penentu kelas penyimpanan statis.

  • Jika variabel ditentukan dalam threadprivate arahan dalam satu unit terjemahan, variabel harus ditentukan dalam threadprivate arahan di setiap unit terjemahan tempat variabel dideklarasikan.

  • Variabel threadprivate tidak boleh muncul dalam klausa apa pun kecuali copyinklausa , , copyprivateschedule, num_threads, atau if .

  • Alamat threadprivate variabel bukan konstanta alamat.

  • Variabel threadprivate tidak boleh memiliki jenis yang tidak lengkap atau jenis referensi.

  • Variabel threadprivate dengan jenis kelas non-POD harus memiliki konstruktor salinan yang dapat diakses dan tidak ambigu jika dideklarasikan dengan penginisialisasi eksplisit.

Contoh berikut menggambarkan bagaimana memodifikasi variabel yang muncul di penginisialisasi dapat menyebabkan perilaku yang tidak ditentukan, dan juga cara menghindari masalah ini dengan menggunakan objek tambahan dan copy-constructor.

int x = 1;
T a(x);
const T b_aux(x); /* Capture value of x = 1 */
T b(b_aux);
#pragma omp threadprivate(a, b)

void f(int n) {
   x++;
   #pragma omp parallel for
   /* In each thread:
   * Object a is constructed from x (with value 1 or 2?)
   * Object b is copy-constructed from b_aux
   */
   for (int i=0; i<n; i++) {
      g(a, b); /* Value of a is unspecified. */
   }
}

Referensi silang

2.7.2 Klausa atribut berbagi data

Beberapa direktif menerima klausul yang memungkinkan pengguna mengontrol atribut berbagi variabel selama durasi wilayah. Klausa atribut berbagi hanya berlaku untuk variabel dalam tingkat leksikal arahan tempat klausa muncul. Tidak semua klausul berikut diizinkan pada semua arahan. Daftar klausul yang valid pada arahan tertentu dijelaskan dengan arahan.

Jika variabel terlihat ketika konstruksi paralel atau berbagi kerja ditemui, dan variabel tidak ditentukan dalam klausa atribut berbagi atau threadprivate arahan, maka variabel dibagikan. Variabel statis yang dideklarasikan dalam tingkat dinamis wilayah paralel dibagikan. Memori yang dialokasikan timbunan (misalnya, menggunakan malloc() di C atau C++ atau new operator di C++) dibagikan. (Penunjuk ke memori ini, bagaimanapun, dapat bersifat privat atau bersama.) Variabel dengan durasi penyimpanan otomatis yang dideklarasikan dalam tingkat dinamis wilayah paralel bersifat privat.

Sebagian besar klausa menerima argumen daftar variabel, yang merupakan daftar variabel yang dipisahkan koma yang terlihat. Jika variabel yang direferensikan dalam klausul atribut berbagi data memiliki jenis yang berasal dari templat, dan tidak ada referensi lain ke variabel tersebut dalam program, perilaku tersebut tidak ditentukan.

Semua variabel yang muncul dalam klausa direktif harus terlihat. Klausul dapat diulang sesuai kebutuhan, tetapi tidak ada variabel yang dapat ditentukan dalam lebih dari satu klausa, kecuali bahwa variabel dapat ditentukan dalam firstprivate klausa dan lastprivate .

Bagian berikut menjelaskan klausa atribut berbagi data:

2.7.2.1 privat

Klausa private mendeklarasikan variabel dalam daftar variabel menjadi privat untuk setiap utas dalam tim. Sintaks private klausul adalah sebagai berikut:

private(variable-list)

Perilaku variabel yang ditentukan dalam private klausul adalah sebagai berikut. Objek baru dengan durasi penyimpanan otomatis dialokasikan untuk konstruksi. Ukuran dan perataan objek baru ditentukan oleh jenis variabel. Alokasi ini terjadi sekali untuk setiap utas dalam tim, dan konstruktor default dipanggil untuk objek kelas jika perlu; jika tidak, nilai awal tidak ditentukan. Objek asli yang dirujuk oleh variabel memiliki nilai yang tidak ditentukan saat masuk ke konstruksi, tidak boleh dimodifikasi dalam jangkauan dinamis konstruksi, dan memiliki nilai yang tidak ditentukan saat keluar dari konstruksi.

Dalam jangkauan leksikal konstruksi direktif, variabel mereferensikan objek privat baru yang dialokasikan oleh utas.

Pembatasan klausul private adalah sebagai berikut:

  • Variabel dengan jenis kelas yang ditentukan dalam private klausul harus memiliki konstruktor default yang dapat diakses dan tidak ambigu.

  • Variabel yang ditentukan dalam private klausul tidak boleh memiliki constjenis -qualified kecuali memiliki jenis kelas dengan mutable anggota.

  • Variabel yang private ditentukan dalam klausa tidak boleh memiliki jenis yang tidak lengkap atau jenis referensi.

  • Variabel yang muncul dalam reduction klausul arahan parallel tidak dapat ditentukan dalam private klausul pada arahan berbagi kerja yang mengikat konstruksi paralel.

2.7.2.2 firstprivate

Klausa firstprivate ini menyediakan superset fungsionalitas yang disediakan oleh private klausul. Sintaks firstprivate klausul adalah sebagai berikut:

firstprivate(variable-list)

Variabel yang ditentukan dalam daftar variabel memiliki private semantik klausa, seperti yang dijelaskan dalam bagian 2.7.2.1. Inisialisasi atau konstruksi terjadi seolah-olah dilakukan sekali per utas, sebelum eksekusi alur konstruksi. firstprivate Untuk klausa pada konstruksi paralel, nilai awal objek privat baru adalah nilai objek asli yang ada segera sebelum konstruksi paralel untuk utas yang menemukannya. firstprivate Untuk klausul pada konstruksi berbagi kerja, nilai awal objek privat baru untuk setiap utas yang menjalankan konstruksi berbagi kerja adalah nilai objek asli yang ada sebelum titik waktu saat utas yang sama menemukan konstruksi berbagi kerja. Selain itu, untuk objek C++, objek privat baru untuk setiap utas dibuat dari objek asli.

Pembatasan klausul firstprivate adalah sebagai berikut:

  • Variabel yang firstprivate ditentukan dalam klausa tidak boleh memiliki jenis yang tidak lengkap atau jenis referensi.

  • Variabel dengan jenis kelas yang ditentukan sebagai firstprivate harus memiliki konstruktor salinan yang dapat diakses dan tidak ambigu.

  • Variabel yang bersifat privat dalam wilayah paralel atau yang muncul dalam reduction klausul arahan parallel tidak dapat ditentukan dalam firstprivate klausul pada arahan berbagi kerja yang mengikat konstruksi paralel.

2.7.2.3 lastprivate

Klausa lastprivate ini menyediakan superset fungsionalitas yang disediakan oleh private klausul. Sintaks lastprivate klausul adalah sebagai berikut:

lastprivate(variable-list)

Variabel yang ditentukan dalam daftar variabel memiliki private semantik klausa. lastprivate Ketika klausul muncul pada arahan yang mengidentifikasi konstruksi berbagi kerja, nilai setiap lastprivate variabel dari perulangan terakhir berurutan dari perulangan terkait, atau arahan bagian terakhir secara leksikal, ditetapkan ke objek asli variabel. Variabel yang tidak diberi nilai oleh iterasi terakhir dari for atau parallel for, atau oleh bagian terakhir leksikal dari sections atau parallel sections direktif, memiliki nilai yang tidak ditentukan setelah konstruksi. Subobjek yang tidak ditetapkan juga memiliki nilai yang tidak ditentukan setelah konstruksi.

Pembatasan klausul lastprivate adalah sebagai berikut:

  • Semua batasan untuk private diterapkan.

  • Variabel dengan jenis kelas yang ditentukan sebagai lastprivate harus memiliki operator penetapan salinan yang dapat diakses dan tidak ambigu.

  • Variabel yang bersifat privat dalam wilayah paralel atau yang muncul dalam reduction klausul arahan parallel tidak dapat ditentukan dalam lastprivate klausul pada arahan berbagi kerja yang mengikat konstruksi paralel.

2.7.2.4 bersama

Klausa ini berbagi variabel yang muncul dalam daftar variabel di antara semua utas dalam tim. Semua utas dalam tim mengakses area penyimpanan yang sama untuk shared variabel.

Sintaks shared klausul adalah sebagai berikut:

shared(variable-list)

2.7.2.5 default

Klausa default memungkinkan pengguna untuk memengaruhi atribut variabel berbagi data. Sintaks default klausul adalah sebagai berikut:

default(shared | none)

Menentukan default(shared) setara dengan secara eksplisit mencantumkan setiap variabel yang shared saat ini terlihat dalam klausul, kecuali jika variabel tersebut threadprivate atau constmemenuhi syarat. Dengan tidak adanya klausul eksplisit default , perilaku default sama seperti jika default(shared) ditentukan.

Menentukan default(none) mengharuskan setidaknya salah satu dari berikut ini harus benar untuk setiap referensi ke variabel dalam tingkat leksikal konstruksi paralel:

  • Variabel secara eksplisit tercantum dalam klausul atribut berbagi data dari konstruksi yang berisi referensi.

  • Variabel dideklarasikan dalam konstruksi paralel.

  • Variabelnya adalah threadprivate.

  • Variabel memiliki constjenis -qualified.

  • Variabel adalah variabel kontrol perulangan untuk perulangan for yang segera mengikuti for atau parallel for direktif, dan referensi variabel muncul di dalam perulangan.

Menentukan variabel pada firstprivate, , lastprivateatau reduction klausul direktif tertutup menyebabkan referensi implisit ke variabel dalam konteks penutup. Referensi implisit tersebut juga tunduk pada persyaratan yang tercantum di atas.

Hanya satu default klausa yang dapat ditentukan pada arahan parallel .

Atribut berbagi data default variabel dapat diganti dengan menggunakan privateklausa , , firstprivate, lastprivatereduction, dan shared , seperti yang ditunjukkan oleh contoh berikut:

#pragma  omp  parallel  for  default(shared)  firstprivate(i)\
   private(x)  private(r)  lastprivate(i)

2.7.2.6 pengurangan

Klausa ini melakukan pengurangan pada variabel skalar yang muncul dalam daftar variabel, dengan operasi operator. Sintaks reduction klausul adalah sebagai berikut:

reduction(Op : daftar variabel )

Pengurangan biasanya ditentukan untuk pernyataan dengan salah satu formulir berikut:

  • x = x op expr
  • x binop = expr
  • x = expr op x (kecuali untuk pengurangan)
  • x ++
  • ++x
  • x --
  • --x

di mana:

x
Salah satu variabel pengurangan yang ditentukan dalam daftar.

daftar variabel
Daftar variabel pengurangan skalar yang dipisahkan koma.

expr
Ekspresi dengan jenis skalar yang tidak mereferensikan x.

op
Bukan operator yang kelebihan beban tetapi salah satu dari +, , -*, &, ^, |, &&, atau ||.

binop
Bukan operator yang kelebihan beban tetapi salah satu dari +, , *, -&, ^, atau |.

Berikut ini adalah contoh reduction klausa:

#pragma omp parallel for reduction(+: a, y) reduction(||: am)
for (i=0; i<n; i++) {
   a += b[i];
   y = sum(y, c[i]);
   am = am || b[i] == c[i];
}

Seperti yang ditunjukkan dalam contoh, operator mungkin disembunyikan di dalam panggilan fungsi. Pengguna harus berhati-hati bahwa operator yang ditentukan dalam reduction klausul cocok dengan operasi pengurangan.

Meskipun operand yang tepat dari || operator tidak memiliki efek samping dalam contoh ini, mereka diizinkan, tetapi harus digunakan dengan hati-hati. Dalam konteks ini, efek samping yang dijamin tidak terjadi selama eksekusi berurutan perulangan dapat terjadi selama eksekusi paralel. Perbedaan ini dapat terjadi karena urutan eksekusi iterasi tidak ditentukan.

Operator digunakan untuk menentukan nilai awal variabel privat apa pun yang digunakan oleh pengkompilasi untuk pengurangan dan untuk menentukan operator finalisasi. Menentukan operator secara eksplisit memungkinkan pernyataan pengurangan berada di luar jangkauan leksikal konstruksi. reduction Sejumlah klausul dapat ditentukan pada direktif, tetapi variabel dapat muncul di paling banyak satu reduction klausa untuk arahan tersebut.

Salinan privat dari setiap variabel dalam daftar variabel dibuat, satu untuk setiap utas, seolah-olah private klausa telah digunakan. Salinan privat diinisialisasi sesuai dengan operator (lihat tabel berikut).

Di akhir wilayah tempat reduction klausul ditentukan, objek asli diperbarui untuk mencerminkan hasil menggabungkan nilai aslinya dengan nilai akhir masing-masing salinan privat menggunakan operator yang ditentukan. Operator pengurangan semuanya asosiatif (kecuali untuk pengurangan), dan pengkompilasi dapat dengan bebas mengaitkan kembali komputasi nilai akhir. (Hasil parsial pengurangan pengurangan ditambahkan untuk membentuk nilai akhir.)

Nilai objek asli menjadi tidak ditentukan ketika utas pertama mencapai klausa yang berisi dan tetap demikian sampai komputasi pengurangan selesai. Biasanya, komputasi akan selesai di akhir konstruksi; namun, jika reduction klausul digunakan pada konstruksi yang nowait juga diterapkan, nilai objek asli tetap tidak ditentukan sampai sinkronisasi penghapus dilakukan untuk memastikan bahwa semua utas telah menyelesaikan reduction klausa.

Tabel berikut mencantumkan operator yang valid dan nilai inisialisasi kanonisnya. Nilai inisialisasi aktual akan konsisten dengan jenis data variabel pengurangan.

Operator Inisialisasi
+ 0
* 1
- 0
& ~0
| 0
^ 0
&& 1
|| 0

Pembatasan klausul reduction adalah sebagai berikut:

  • Jenis variabel dalam reduction klausa harus valid untuk operator pengurangan kecuali bahwa jenis penunjuk dan jenis referensi tidak pernah diizinkan.

  • Variabel yang ditentukan dalam reduction klausul tidak boleh const-memenuhi syarat.

  • Variabel yang bersifat privat dalam wilayah paralel atau yang muncul dalam reduction klausul arahan parallel tidak dapat ditentukan dalam reduction klausul pada arahan berbagi kerja yang mengikat konstruksi paralel.

    #pragma omp parallel private(y)
    { /* ERROR - private variable y cannot be specified
                  in a reduction clause */
        #pragma omp for reduction(+: y)
        for (i=0; i<n; i++)
           y += b[i];
    }
    
    /* ERROR - variable x cannot be specified in both
                a shared and a reduction clause */
    #pragma omp parallel for shared(x) reduction(+: x)
    

2.7.2.7 copyin

Klausul ini copyin menyediakan mekanisme untuk menetapkan nilai yang sama ke threadprivate variabel untuk setiap utas dalam tim yang menjalankan wilayah paralel. Untuk setiap variabel yang ditentukan dalam copyin klausul, nilai variabel dalam utas master tim disalin, seolah-olah berdasarkan penugasan, ke salinan thread-private di awal wilayah paralel. Sintaks copyin klausul adalah sebagai berikut:

copyin(
variable-list
)

Pembatasan klausul copyin adalah sebagai berikut:

  • Variabel yang ditentukan dalam copyin klausul harus memiliki operator penetapan salinan yang dapat diakses dan tidak ambigu.

  • Variabel yang ditentukan dalam copyin klausul harus berupa threadprivate variabel.

2.7.2.8 copyprivate

Klausul ini copyprivate menyediakan mekanisme untuk menggunakan variabel privat untuk menyiarkan nilai dari satu anggota tim ke anggota lainnya. Ini adalah alternatif untuk menggunakan variabel bersama untuk nilai saat menyediakan variabel bersama seperti itu akan sulit (misalnya, dalam rekursi yang memerlukan variabel yang berbeda di setiap tingkat). Klausa copyprivate hanya dapat muncul pada arahan single .

Sintaks copyprivate klausul adalah sebagai berikut:

copyprivate(
variable-list
)

Efek copyprivate klausul pada variabel dalam daftar variabelnya terjadi setelah eksekusi blok terstruktur yang terkait dengan single konstruksi, dan sebelum salah satu utas dalam tim telah meninggalkan penghalang di akhir konstruksi. Kemudian, di semua utas lain dalam tim, untuk setiap variabel dalam daftar variabel, variabel tersebut menjadi ditentukan (seolah-olah berdasarkan penugasan) dengan nilai variabel yang sesuai dalam utas yang menjalankan blok terstruktur konstruksi.

Pembatasan klausul copyprivate adalah sebagai berikut:

  • Variabel yang ditentukan dalam copyprivate klausul tidak boleh muncul dalam private klausa atau firstprivate untuk arahan yang sama single .

  • single Jika direktif dengan copyprivate klausul ditemui dalam tingkat dinamis wilayah paralel, semua variabel yang ditentukan dalam copyprivate klausul harus privat dalam konteks penutup.

  • Variabel yang ditentukan dalam copyprivate klausul harus memiliki operator penetapan salinan yang tidak ambigu yang dapat diakses.

2.8 Pengikatan arahan

Pengikatan dinamis arahan harus mematuhi aturan berikut:

  • Arahan for, , sectionssingle, master, dan barrier mengikat ke direktif yang secara dinamis mengapit parallel, jika ada, terlepas dari nilai klausul apa pun if yang mungkin ada pada arahan tersebut. Jika saat ini tidak ada wilayah paralel yang dijalankan, arahan dijalankan oleh tim yang hanya terdiri dari utas master.

  • Direktif ordered mengikat ke yang tertutup forsecara dinamis .

  • Arahan atomic memberlakukan akses eksklusif sehubungan atomic dengan arahan di semua utas, bukan hanya tim saat ini.

  • Arahan critical memberlakukan akses eksklusif sehubungan critical dengan arahan di semua utas, bukan hanya tim saat ini.

  • Direktif tidak pernah dapat mengikat ke arahan apa pun di luar yang tertutup secara paralleldinamis terdekat .

2.9 Direktif bersarang

Penyarangan direktif dinamis harus mematuhi aturan berikut:

  • Direktif parallel secara dinamis di dalam tim lain parallel secara logis membentuk tim baru, yang hanya terdiri dari utas saat ini, kecuali paralelisme berlapis diaktifkan.

  • for, sections, dan single arahan yang mengikat ke hal yang sama parallel tidak diizinkan untuk disarangkan di dalam satu sama lain.

  • critical direktif dengan nama yang sama tidak diizinkan untuk disarangkan di dalam satu sama lain. Perhatikan bahwa pembatasan ini tidak cukup untuk mencegah kebuntuan.

  • for, sections, dan single direktif tidak diizinkan dalam tingkat criticaldinamis wilayah , , ordereddan master jika arahan mengikat sama parallel dengan wilayah.

  • barrierdirektif tidak diizinkan dalam tingkat fordinamis wilayah , , ordered, sectionssingle, master, dan critical jika arahan mengikat sama parallel dengan wilayah.

  • masterdirektif tidak diizinkan dalam tingkat dinamis , , sectionsdan single arahan forjika master arahan mengikat sama parallel dengan arahan berbagi kerja.

  • ordered direktif tidak diizinkan dalam tingkat critical dinamis wilayah jika arahan mengikat sama parallel dengan wilayah.

  • Arahan apa pun yang diizinkan saat dijalankan secara dinamis di dalam wilayah paralel juga diizinkan saat dijalankan di luar wilayah paralel. Ketika dijalankan secara dinamis di luar wilayah paralel yang ditentukan pengguna, arahan dijalankan oleh tim yang hanya terdiri dari utas master.