Bagikan melalui


J. Contoh

Berikut ini adalah contoh konstruksi yang ditentukan dalam dokumen ini. Pernyataan yang mengikuti direktif hanya senyawa jika perlu, dan pernyataan non-gabungan diindentasi dari arahan sebelumnya.

A.1 Perulangan sederhana secara paralel

Contoh berikut menunjukkan cara memparalelkan perulangan menggunakan paralel untuk direktif. Variabel iterasi perulangan bersifat privat secara default, sehingga tidak perlu menentukannya secara eksplisit dalam klausa privat.

#pragma omp parallel for
    for (i=1; i<n; i++)
        b[i] = (a[i] + a[i-1]) / 2.0;

Kompilasi Bersyarkala A.2

Contoh berikut mengilustrasikan penggunaan kompilasi kondisional menggunakan _OPENMP makro OpenMP. Dengan kompilasi OpenMP, _OPENMP makro menjadi ditentukan.

# ifdef _OPENMP
    printf_s("Compiled by an OpenMP-compliant implementation.\n");
# endif

Operator praprosesor yang ditentukan memungkinkan lebih dari satu makro diuji dalam satu arahan.

# if defined(_OPENMP) && defined(VERBOSE)
    printf_s("Compiled by an OpenMP-compliant implementation.\n");
# endif

Wilayah A.3 Paralel

Arahan paralel dapat digunakan dalam program paralel kasar-grain. Dalam contoh berikut, setiap utas di wilayah paralel memutuskan bagian mana dari array x global yang akan dikerjakan, berdasarkan nomor utas:

#pragma omp parallel shared(x, npoints) private(iam, np, ipoints)
{
    iam = omp_get_thread_num();
    np =  omp_get_num_threads();
    ipoints = npoints / np;
    subdomain(x, iam, ipoints);
}

A.4 Klausa nowait

Jika ada banyak perulangan independen dalam wilayah paralel, Anda dapat menggunakan klausul nowait untuk menghindari penghambat tersirat di akhir arahan for , sebagai berikut:

#pragma omp parallel
{
    #pragma omp for nowait
        for (i=1; i<n; i++)
             b[i] = (a[i] + a[i-1]) / 2.0;
    #pragma omp for nowait
        for (i=0; i<m; i++)
            y[i] = sqrt(z[i]);
}

A.5 Arahan kritis

Contoh berikut mencakup beberapa arahan penting . Contoh mengilustrasikan model antrean di mana tugas dihentikan dan dikerjakan. Untuk menjaga dari banyak utas yang mengantre tugas yang sama, operasi penghapusan antrean harus berada di bagian critical . Karena kedua antrean dalam contoh ini bersifat independen, antrean dilindungi oleh critical arahan dengan nama, xaxis, dan yaxis yang berbeda.

#pragma omp parallel shared(x, y) private(x_next, y_next)
{
    #pragma omp critical ( xaxis )
        x_next = dequeue(x);
    work(x_next);
    #pragma omp critical ( yaxis )
        y_next = dequeue(y);
    work(y_next);
}

A.6 Klausa lastprivate

Eksekusi yang benar terkadang tergantung pada nilai yang ditetapkan iterasi terakhir dari perulangan ke variabel. Program tersebut harus mencantumkan semua variabel seperti argumen ke klausul lastprivate sehingga nilai variabel sama seperti ketika perulangan dijalankan secara berurutan.

#pragma omp parallel
{
   #pragma omp for lastprivate(i)
      for (i=0; i<n-1; i++)
         a[i] = b[i] + b[i+1];
}
a[i]=b[i];

Dalam contoh sebelumnya, nilai i di akhir wilayah paralel akan sama dengan n-1, seperti dalam kasus berurutan.

A.7 Klausa pengurangan

Contoh berikut menunjukkan klausa pengurangan :

#pragma omp parallel for private(i) shared(x, y, n) \
                         reduction(+: a, b)
    for (i=0; i<n; i++) {
        a = a + x[i];
        b = b + y[i];
    }

Bagian Paralel A.8

Dalam contoh berikut (untuk bagian 2.4.2), fungsi xaxis, yaxis, dan zaxis dapat dijalankan secara bersamaan. Direktif pertama section bersifat opsional. Semua section direktif perlu muncul dalam jangkauan parallel sections leksikal konstruksi.

#pragma omp parallel sections
{
    #pragma omp section
        xaxis();
    #pragma omp section
        yaxis();
    #pragma omp section
        zaxis();
}

Direktif tunggal A.9

Contoh berikut menunjukkan arahan tunggal . Dalam contoh, hanya satu utas (biasanya utas pertama yang menemukan arahan single ) mencetak pesan kemajuan. Pengguna tidak boleh membuat asumsi apa pun mengenai utas mana yang akan menjalankan bagian .single Semua utas lainnya akan melewati bagian single dan berhenti di penghadang di akhir single konstruksi. Jika utas lain dapat dilanjutkan tanpa menunggu utas menjalankan single bagian, nowait klausa dapat ditentukan pada arahan single .

#pragma omp parallel
{
    #pragma omp single
        printf_s("Beginning work1.\n");
    work1();
    #pragma omp single
        printf_s("Finishing work1.\n");
    #pragma omp single nowait
        printf_s("Finished work1 and beginning work2.\n");
    work2();
}

Urutan berurutan A.10

Bagian yang diurutkan berguna untuk secara berurutan mengurutkan output dari pekerjaan yang dilakukan secara paralel. Program berikut mencetak indeks secara berurutan:

#pragma omp for ordered schedule(dynamic)
    for (i=lb; i<ub; i+=st)
        work(i);
void work(int k)
{
    #pragma omp ordered
        printf_s(" %d", k);
}

A.11 Jumlah utas tetap

Beberapa program mengandalkan jumlah utas tetap yang telah ditentukan untuk dijalankan dengan benar. Karena pengaturan default untuk penyesuaian dinamis jumlah utas ditentukan implementasi, program tersebut dapat memilih untuk menonaktifkan kemampuan utas dinamis dan mengatur jumlah utas secara eksplisit untuk menjaga portabilitas. Contoh berikut menunjukkan cara melakukan ini menggunakan omp_set_dynamic, dan omp_set_num_threads:

omp_set_dynamic(0);
omp_set_num_threads(16);
#pragma omp parallel shared(x, npoints) private(iam, ipoints)
{
    if (omp_get_num_threads() != 16)
      abort();
    iam = omp_get_thread_num();
    ipoints = npoints/16;
    do_by_16(x, iam, ipoints);
}

Dalam contoh ini, program dijalankan dengan benar hanya jika dijalankan oleh 16 utas. Jika implementasi tidak mampu mendukung 16 utas, perilaku contoh ini ditentukan implementasi.

Jumlah utas yang menjalankan wilayah paralel tetap konstan selama wilayah paralel, terlepas dari pengaturan utas dinamis. Mekanisme utas dinamis menentukan jumlah utas yang akan digunakan di awal wilayah paralel dan membuatnya tetap konstan selama durasi wilayah.

A.12 Direktif atom

Contoh berikut menghindari kondisi balapan (pembaruan simultan dari elemen x oleh banyak utas) dengan menggunakan direktif atom :

#pragma omp parallel for shared(x, y, index, n)
    for (i=0; i<n; i++)
    {
        #pragma omp atomic
            x[index[i]] += work1(i);
        y[i] += work2(i);
    }

Keuntungan menggunakan arahan atomic dalam contoh ini adalah memungkinkan pembaruan dari dua elemen x yang berbeda terjadi secara paralel. Jika arahan kritis digunakan sebagai gantinya, maka semua pembaruan untuk elemen x dijalankan secara serial (meskipun tidak dalam urutan yang dijamin).

Direktif atomic hanya berlaku untuk pernyataan C atau C++ segera mengikutinya. Akibatnya, elemen y tidak diperbarui secara atomik dalam contoh ini.

A.13 Arahan flush dengan daftar

Contoh berikut menggunakan direktif flush untuk sinkronisasi titik-ke-titik objek tertentu antara pasangan utas:

int   sync[NUMBER_OF_THREADS];
float work[NUMBER_OF_THREADS];
#pragma omp parallel private(iam,neighbor) shared(work,sync)
{
    iam = omp_get_thread_num();
    sync[iam] = 0;
    #pragma omp barrier

    // Do computation into my portion of work array
    work[iam] = ...;

    //  Announce that I am done with my work
    // The first flush ensures that my work is
    // made visible before sync.
    // The second flush ensures that sync is made visible.
    #pragma omp flush(work)
    sync[iam] = 1;
    #pragma omp flush(sync)

    // Wait for neighbor
    neighbor = (iam>0 ? iam : omp_get_num_threads()) - 1;
    while (sync[neighbor]==0)
    {
        #pragma omp flush(sync)
    }

    // Read neighbor's values of work array
    ... = work[neighbor];
}

A.14 Arahan flush tanpa daftar

Contoh berikut (untuk bagian 2.6.5) membedakan objek bersama yang flush terpengaruh oleh arahan tanpa daftar dari objek bersama yang tidak terpengaruh:

// omp_flush_without_list.c
#include <omp.h>

int x, *p = &x;

void f1(int *q)
{
    *q = 1;
    #pragma omp flush
    // x, p, and *q are flushed
    //   because they are shared and accessible
    // q is not flushed because it is not shared.
}

void f2(int *q)
{
    #pragma omp barrier
    *q = 2;

    #pragma omp barrier
    // a barrier implies a flush
    // x, p, and *q are flushed
    //   because they are shared and accessible
    // q is not flushed because it is not shared.
}

int g(int n)
{
    int i = 1, j, sum = 0;
    *p = 1;

    #pragma omp parallel reduction(+: sum) num_threads(10)
    {
        f1(&j);
        // i, n and sum were not flushed
        //   because they were not accessible in f1
        // j was flushed because it was accessible
        sum += j;
        f2(&j);
        // i, n, and sum were not flushed
        //   because they were not accessible in f2
        // j was flushed because it was accessible
        sum += i + j + *p + n;
    }
    return sum;
}

int main()
{
}

A.15 Jumlah utas yang digunakan

Pertimbangkan contoh yang salah berikut (untuk bagian 3.1.2):

np = omp_get_num_threads(); // misplaced
#pragma omp parallel for schedule(static)
    for (i=0; i<np; i++)
        work(i);

Panggilan omp_get_num_threads() mengembalikan 1 di bagian seri kode, sehingga np akan selalu sama dengan 1 dalam contoh sebelumnya. Untuk menentukan jumlah utas yang akan disebarkan untuk wilayah paralel, panggilan harus berada di dalam wilayah paralel.

Contoh berikut menunjukkan cara menulis ulang program ini tanpa menyertakan kueri untuk jumlah utas:

#pragma omp parallel private(i)
{
    i = omp_get_thread_num();
    work(i);
}

Kunci A.16

Dalam contoh berikut (untuk bagian 3.2), argumen ke fungsi kunci harus memiliki jenis omp_lock_t, dan bahwa tidak perlu menghapusnya. Fungsi kunci menyebabkan utas menganggur sambil menunggu entri ke bagian penting pertama, tetapi untuk melakukan pekerjaan lain sambil menunggu entri ke yang kedua. Fungsi omp_set_lock memblokir, tetapi omp_test_lock fungsi tidak, memungkinkan pekerjaan skip() di selesai.

// omp_using_locks.c
// compile with: /openmp /c
#include <stdio.h>
#include <omp.h>

void work(int);
void skip(int);

int main() {
   omp_lock_t lck;
   int id;

   omp_init_lock(&lck);
   #pragma omp parallel shared(lck) private(id)
   {
      id = omp_get_thread_num();

      omp_set_lock(&lck);
      printf_s("My thread id is %d.\n", id);

      // only one thread at a time can execute this printf
      omp_unset_lock(&lck);

      while (! omp_test_lock(&lck)) {
         skip(id);   // we do not yet have the lock,
                     // so we must do something else
      }
      work(id);     // we now have the lock
                    // and can do the work
      omp_unset_lock(&lck);
   }
   omp_destroy_lock(&lck);
}

Kunci A.17 yang dapat disarangkan

Contoh berikut (untuk bagian 3.2) menunjukkan bagaimana kunci berlapis dapat digunakan untuk menyinkronkan pembaruan baik ke seluruh struktur maupun ke salah satu anggotanya.

#include <omp.h>
typedef struct {int a,b; omp_nest_lock_t lck;} pair;

void incr_a(pair *p, int a)
{
    // Called only from incr_pair, no need to lock.
    p->a += a;
}

void incr_b(pair *p, int b)
{
    // Called both from incr_pair and elsewhere,
    // so need a nestable lock.

    omp_set_nest_lock(&p->lck);
    p->b += b;
    omp_unset_nest_lock(&p->lck);
}

void incr_pair(pair *p, int a, int b)
{
    omp_set_nest_lock(&p->lck);
    incr_a(p, a);
    incr_b(p, b);
    omp_unset_nest_lock(&p->lck);
}

void f(pair *p)
{
    extern int work1(), work2(), work3();
    #pragma omp parallel sections
    {
        #pragma omp section
            incr_pair(p, work1(), work2());
        #pragma omp section
            incr_b(p, work3());
    }
}

A.18 Berlapis untuk arahan

Contoh forbersarang direktif berikut sesuai karena arahan dalam dan luar for mengikat ke wilayah paralel yang berbeda:

#pragma omp parallel default(shared)
{
    #pragma omp for
        for (i=0; i<n; i++)
        {
            #pragma omp parallel shared(i, n)
            {
                #pragma omp for
                    for (j=0; j<n; j++)
                        work(i, j);
            }
        }
}

Variasi contoh sebelumnya berikut juga sesuai:

#pragma omp parallel default(shared)
{
    #pragma omp for
        for (i=0; i<n; i++)
            work1(i, n);
}

void work1(int i, int n)
{
    int j;
    #pragma omp parallel default(shared)
    {
        #pragma omp for
            for (j=0; j<n; j++)
                work2(i, j);
    }
    return;
}

Contoh A.19 memperlihatkan sarang arahan berbagi kerja yang salah

Contoh di bagian ini menggambarkan aturan berlapis direktif.

Contoh berikut tidak sesuai karena arahan dalam dan luar for disarangkan dan diikat ke arahan yang sama parallel :

void wrong1(int n)
{
  #pragma omp parallel default(shared)
  {
      int i, j;
      #pragma omp for
      for (i=0; i<n; i++) {
          #pragma omp for
              for (j=0; j<n; j++)
                 work(i, j);
     }
   }
}

Versi berlapis dinamis berikut dari contoh sebelumnya juga tidak patuh:

void wrong2(int n)
{
  #pragma omp parallel default(shared)
  {
    int i;
    #pragma omp for
      for (i=0; i<n; i++)
        work1(i, n);
  }
}

void work1(int i, int n)
{
  int j;
  #pragma omp for
    for (j=0; j<n; j++)
      work2(i, j);
}

Contoh berikut tidak patuh karena arahan for dan single ditumpuk, dan diikat ke wilayah paralel yang sama:

void wrong3(int n)
{
  #pragma omp parallel default(shared)
  {
    int i;
    #pragma omp for
      for (i=0; i<n; i++) {
        #pragma omp single
          work(i);
      }
  }
}

Contoh berikut tidak patuh karena barrier arahan di dalam for dapat mengakibatkan kebuntuan:

void wrong4(int n)
{
  #pragma omp parallel default(shared)
  {
    int i;
    #pragma omp for
      for (i=0; i<n; i++) {
        work1(i);
        #pragma omp barrier
        work2(i);
      }
  }
}

Contoh berikut tidak sesuai karena barrier menghasilkan kebuntuan karena fakta bahwa hanya satu utas pada satu waktu yang dapat memasuki bagian penting:

void wrong5()
{
  #pragma omp parallel
  {
    #pragma omp critical
    {
       work1();
       #pragma omp barrier
       work2();
    }
  }
}

Contoh berikut tidak sesuai karena barrier menghasilkan kebuntuan karena fakta bahwa hanya satu utas single yang menjalankan bagian :

void wrong6()
{
  #pragma omp parallel
  {
    setup();
    #pragma omp single
    {
      work1();
      #pragma omp barrier
      work2();
    }
    finish();
  }
}

Direktif pengikat A.20

Aturan pengikatan direktif meminta barrier arahan untuk mengikat ke arahan parallel penutup terdekat. Untuk informasi selengkapnya tentang pengikatan direktif, lihat bagian 2.8.

Dalam contoh berikut, panggilan dari utama ke sub2 sesuai karena (dalam sub3) mengikat ke wilayah paralel di barrier. Panggilan dari utama ke sub1 sesuai karena barrier mengikat ke wilayah paralel di subroutine sub2. Panggilan dari utama ke sub3 sesuai karena barrier tidak mengikat ke wilayah paralel apa pun dan diabaikan. Selain itu, satu-satunya barrier menyinkronkan tim utas di wilayah paralel yang mencakup dan tidak semua utas yang dibuat di sub1.

int main()
{
    sub1(2);
    sub2(2);
    sub3(2);
}

void sub1(int n)
{
    int i;
    #pragma omp parallel private(i) shared(n)
    {
        #pragma omp for
        for (i=0; i<n; i++)
            sub2(i);
    }
}

void sub2(int k)
{
     #pragma omp parallel shared(k)
     sub3(k);
}

void sub3(int n)
{
    work(n);
    #pragma omp barrier
    work(n);
}

Variabel Cakupan A.21 dengan klausa privat

i Nilai dan j dalam contoh berikut tidak ditentukan saat keluar dari wilayah paralel:

int i, j;
i = 1;
j = 2;
#pragma omp parallel private(i) firstprivate(j)
{
  i = 3;
  j = j + 2;
}
printf_s("%d %d\n", i, j);

Untuk informasi selengkapnya tentang private klausa, lihat bagian 2.7.2.1.

A.22 Klausa default(none)

Contoh berikut membedakan variabel yang dipengaruhi oleh default(none) klausul dari variabel yang tidak:

// openmp_using_clausedefault.c
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

int x, y, z[1000];
#pragma omp threadprivate(x)

void fun(int a) {
   const int c = 1;
   int i = 0;

   #pragma omp parallel default(none) private(a) shared(z)
   {
      int j = omp_get_num_thread();
             //O.K.  - j is declared within parallel region
      a = z[j];       // O.K.  - a is listed in private clause
                      //      - z is listed in shared clause
      x = c;          // O.K.  - x is threadprivate
                      //      - c has const-qualified type
      z[i] = y;       // C3052 error - cannot reference i or y here

      #pragma omp for firstprivate(y)
         for (i=0; i<10 ; i++) {
            z[i] = y;  // O.K. - i is the loop control variable
                       // - y is listed in firstprivate clause
          }
       z[i] = y;   // Error - cannot reference i or y here
   }
}

Untuk informasi selengkapnya tentang default klausa, lihat bagian 2.7.2.5.

A.23 Contoh direktif yang diurutkan

Dimungkinkan untuk memiliki banyak bagian yang diurutkan dengan yang for ditentukan dengan ordered klausul. Contoh pertama tidak patuh karena API menentukan aturan berikut:

"Iterasi perulangan dengan for konstruksi tidak boleh menjalankan arahan yang sama ordered lebih dari sekali, dan tidak boleh menjalankan lebih dari satu ordered arahan." (Lihat bagian 2.6.6.)

Dalam contoh yang tidak patuh ini, semua iterasi menjalankan dua bagian yang diurutkan:

#pragma omp for ordered
for (i=0; i<n; i++)
{
    ...
    #pragma omp ordered
    { ... }
    ...
    #pragma omp ordered
    { ... }
    ...
}

Contoh yang sesuai berikut menunjukkan for dengan lebih dari satu bagian yang diurutkan:

#pragma omp for ordered
for (i=0; i<n; i++)
{
    ...
    if (i <= 10)
    {
        ...
        #pragma omp ordered
        { ... }
    }
    ...
    (i > 10)
    {
        ...
        #pragma omp ordered
        { ... }
    }
    ...
}

A.24 Contoh klausul privat

Klausul privat dari wilayah paralel hanya berlaku untuk tingkat leksikal wilayah, bukan untuk tingkat dinamis wilayah. Oleh karena itu, dalam contoh berikut, setiap penggunaan variabel afor dalam perulangan dalam rutin f mengacu pada salinan privat a, sementara penggunaan dalam g rutin mengacu pada global a.

int a;

void f(int n)
{
    a = 0;

    #pragma omp parallel for private(a)
    for (int i=1; i<n; i++)
    {
        a = i;
        g(i, n);
        d(a);     // Private copy of "a"
        ...
    }
    ...

void g(int k, int n)
{
    h(k,a); // The global "a", not the private "a" in f
}

A.25 Contoh klausul atribut data copyprivate

Contoh 1: Klausa copyprivate dapat digunakan untuk menyiarkan nilai yang diperoleh oleh satu utas langsung ke semua instans variabel privat di utas lain.

float x, y;
#pragma omp threadprivate(x, y)

void init( )
{
    float a;
    float b;

    #pragma omp single copyprivate(a,b,x,y)
    {
        get_values(a,b,x,y);
    }

    use_values(a, b, x, y);
}

Jika init rutin dipanggil dari wilayah serial, perilakunya tidak terpengaruh oleh kehadiran arahan. Setelah panggilan ke rutinitas get_values dijalankan oleh satu utas, tidak ada utas yang meninggalkan konstruksi sampai objek privat yang ditunjuk oleh a, b, x, dan y di semua utas telah ditentukan dengan nilai yang dibaca.

Contoh 2: Berbeda dengan contoh sebelumnya, misalkan bacaan harus dilakukan oleh utas tertentu, ucapkan utas master. Dalam hal ini, copyprivate klausul tidak dapat digunakan untuk melakukan siaran secara langsung, tetapi dapat digunakan untuk menyediakan akses ke objek bersama sementara.

float read_next( )
{
    float * tmp;
    float return_val;

    #pragma omp single copyprivate(tmp)
    {
        tmp = (float *) malloc(sizeof(float));
    }

    #pragma omp master
    {
        get_float( tmp );
    }

    #pragma omp barrier
    return_val = *tmp;
    #pragma omp barrier

    #pragma omp single
    {
       free(tmp);
    }

    return return_val;
}

Contoh 3: Misalkan jumlah objek kunci yang diperlukan dalam wilayah paralel tidak dapat dengan mudah ditentukan sebelum memasukkannya. Klausa copyprivate dapat digunakan untuk menyediakan akses ke objek kunci bersama yang dialokasikan dalam wilayah paralel tersebut.

#include <omp.h>

omp_lock_t *new_lock()
{
    omp_lock_t *lock_ptr;

    #pragma omp single copyprivate(lock_ptr)
    {
        lock_ptr = (omp_lock_t *) malloc(sizeof(omp_lock_t));
        omp_init_lock( lock_ptr );
    }

    return lock_ptr;
}

A.26 Direktif threadprivate

Contoh berikut menunjukkan cara menggunakan arahan threadprivate untuk memberi setiap utas penghitung terpisah.

Contoh 1

int counter = 0;
#pragma omp threadprivate(counter)

int sub()
{
    counter++;
    return(counter);
}

Contoh 2

int sub()
{
    static int counter = 0;
    #pragma omp threadprivate(counter)
    counter++;
    return(counter);
}

Array panjang variabel A.27 C99

Contoh berikut menunjukkan cara menggunakan C99 Variable Length Arrays (VLA) dalam direktif firstprivate .

Catatan

Array panjang variabel saat ini tidak didukung di Visual C++.

void f(int m, int C[m][m])
{
    double v1[m];
    ...
    #pragma omp parallel firstprivate(C, v1)
    ...
}

A.28 Klausa num_threads

Contoh berikut menunjukkan klausa num_threads . Wilayah paralel dijalankan dengan maksimum 10 utas.

#include <omp.h>
int main()
{
    omp_set_dynamic(1);
    ...
    #pragma omp parallel num_threads(10)
    {
        ... parallel region ...
    }
}

A.29 Konstruksi berbagi kerja di dalam konstruksi kritis

Contoh berikut menunjukkan penggunaan konstruksi berbagi kerja di dalam critical konstruksi. Contoh ini sesuai karena konstruksi berbagi kerja dan critical konstruksi tidak mengikat ke wilayah paralel yang sama.

void f()
{
  int i = 1;
  #pragma omp parallel sections
  {
    #pragma omp section
    {
      #pragma omp critical (name)
      {
        #pragma omp parallel
        {
          #pragma omp single
          {
            i++;
          }
        }
      }
    }
  }
}

Reprivatisasi A.30

Contoh berikut menunjukkan reprivatisasi variabel. Variabel privat dapat ditandai private lagi dalam arahan berlapis. Anda tidak perlu berbagi variabel tersebut di wilayah paralel yang tertutup.

int i, a;
...
#pragma omp parallel private(a)
{
  ...
  #pragma omp parallel for private(a)
  for (i=0; i<10; i++)
     {
       ...
     }
}

Fungsi kunci A.31 Thread-safe

Contoh C++ berikut menunjukkan cara menginisialisasi array kunci di wilayah paralel dengan menggunakan omp_init_lock.

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

omp_lock_t *new_locks() {
   int i;
   omp_lock_t *lock = new omp_lock_t[1000];
   #pragma omp parallel for private(i)
   for (i = 0 ; i < 1000 ; i++)
      omp_init_lock(&lock[i]);

   return lock;
}

int main () {}