Aracılığıyla paylaş


A. Örnekler

Aşağıda, bu belgede tanımlanan yapıların örnekleri verilmiştir. Yönergeyi izleyen bir deyim yalnızca gerektiğinde bileşiktir ve bileşik olmayan bir deyim kendisinden önceki bir yönergeden girintili olur.

A.1 Paralel olarak basit bir döngü

Aşağıdaki örnek, yönergesi için paralel kullanarak bir döngünün nasıl paralelleştirilmek üzere yapıldığını gösterir. Döngü yineleme değişkeni varsayılan olarak özeldir, bu nedenle özel yan tümcesinde açıkça belirtilmesi gerekmez.

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

A.2 Koşullu derleme

Aşağıdaki örneklerde, OpenMP makro _OPENMP kullanılarak koşullu derleme kullanımı gösterilmektedir. OpenMP derlemesi ile _OPENMP makro tanımlanır.

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

Tanımlanan önişlemci işleci, birden fazla makronun tek bir yönergede test edilmesini sağlar.

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

A.3 Paralel bölgeler

Paralel yönerge, kaba taneli paralel programlarda kullanılabilir. Aşağıdaki örnekte, paralel bölgedeki her iş parçacığı, iş parçacığı numarasına göre genel dizinin x hangi bölümünde çalışacağına karar verir:

#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 Nowait yan tümcesi

Paralel bir bölgede çok sayıda bağımsız döngü varsa, yönergenin sonundaki yan tümcesini aşağıdaki gibi kullanabilirsiniz:

#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 Kritik yönerge

Aşağıdaki örnek birkaç kritik yönerge içerir. Örnekte, bir görevin sıralandığı ve üzerinde çalışıldığı bir kuyruğa alma modeli gösterilmektedir. Aynı görevi sıralayan birçok iş parçacığına karşı koruma sağlamak için, sıralama işleminin bir critical bölümde olması gerekir. Bu örnekteki iki kuyruk bağımsız olduğundan, bunlar xaxis ve critical gibi farklı adlara sahip yönergelerle korunur.

#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 Lastprivate yan tümcesi

Doğru yürütme bazen döngünün son yinelemesinin bir değişkene atamış olduğu değere bağlıdır. Bu tür programlar tüm bu değişkenleri lastprivate yan tümcesine bağımsız değişken olarak listelemelidir, böylece değişkenlerin değerleri döngü sırayla yürütülürken olduğu gibi aynı olur.

#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];

Yukarıdaki örnekte paralel bölgenin sonundaki değeri i , sıralı durumda olduğu gibi değerine eşit n-1olacaktır.

A.7 Azaltma yan tümcesi

Aşağıdaki örnekte azaltma yan tümcesi gösterilmektedir:

#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];
    }

A.8 Paralel bölümler

Aşağıdaki örnekte (bölüm 2.4.2 için), xaxis, yaxis ve zaxis işlevleri eşzamanlı olarak yürütülebilir. İlk section yönerge isteğe bağlıdır. Tüm section yönergelerin, yapısının sözcük temelli kapsamında parallel sections görünmesi gerekir.

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

A.9 Tek yönergeleri

Aşağıdaki örnekte tek yönerge gösterilmektedir. Örnekte yalnızca bir iş parçacığı (genellikle yönergeyle single karşılaşan ilk iş parçacığı) ilerleme iletisini yazdırır. Kullanıcı, hangi iş parçacığının bölümü yürüteceğiyle ilgili hiçbir varsayımda single bulunmamalıdır. Diğer tüm iş parçacıkları bölümü atlar single ve yapı sonundaki single bariyerde durur. Diğer iş parçacıkları, bölümü yürüten single iş parçacığını beklemeden devam edebilirse yönergesinde nowait bir single yan tümce belirtilebilir.

#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();
}

A.10 Sıralı sıralama

Sıralı bölümler , paralel olarak yapılan işten çıkışı sıralı olarak sıralamak için kullanışlıdır. Aşağıdaki program dizinleri sıralı sırada yazdırır:

#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 Sabit sayıda iş parçacığı

Bazı programlar doğru şekilde yürütülecek sabit, önceden belirtilmemiş sayıda iş parçacığını destekler. İş parçacığı sayısının dinamik olarak ayarlanması için varsayılan ayar uygulama tanımlı olduğundan, bu tür programlar dinamik iş parçacıkları özelliğini kapatmayı ve taşınabilirliği korumak için iş parçacığı sayısını açıkça ayarlamayı seçebilir. Aşağıdaki örnek, omp_set_dynamic ve omp_set_num_threads kullanarak bunun nasıl yapılacağını gösterir:

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);
}

Bu örnekte, program yalnızca 16 iş parçacığı tarafından yürütülürse doğru şekilde yürütülür. Uygulama 16 iş parçacığını destekleyemiyorsa, bu örneğin davranışı uygulama tanımlıdır.

Paralel bölge yürüten iş parçacıklarının sayısı, dinamik iş parçacıkları ayarından bağımsız olarak paralel bölge sırasında sabit kalır. Dinamik iş parçacıkları mekanizması, paralel bölgenin başlangıcında kullanılacak iş parçacığı sayısını belirler ve bölge süresi boyunca sabit tutar.

A.12 Atomik yönerge

Aşağıdaki örnek, atomik yönergesini kullanarak yarış koşullarını (birçok iş parçacığı tarafından x öğesinin eşzamanlı güncelleştirmeleri) önler:

#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);
    }

Bu örnekte yönergesini atomic kullanmanın avantajı, x'in iki farklı öğesinin güncelleştirmelerinin paralel olarak gerçekleşmesine izin vermesidir. Bunun yerine kritik bir yönerge kullanılırsa, x öğelerinin tüm güncelleştirmeleri seri olarak yürütülür (ancak hiçbir garanti sırasına göre yürütülemez).

yönergesi atomic yalnızca hemen ardından gelen C veya C++ deyimi için geçerlidir. Sonuç olarak, y öğeleri bu örnekte atomik olarak güncelleştirilmez.

A.13 Listeli temizleme yönergesi

Aşağıdaki örnek, belirli nesnelerin iş parçacığı çiftleri arasında noktadan noktaya eşitleme için yönergesini kullanır flush :

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 Liste olmadan temizleme yönergesi

Aşağıdaki örnek (bölüm 2.6.5 için), liste içermeyen bir flush yönergeden etkilenen paylaşılan nesneleri, etkilenmeyen paylaşılan nesnelerden ayırır:

// 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 Kullanılan iş parçacığı sayısı

Aşağıdaki yanlış örneği göz önünde bulundurun (bölüm 3.1.2 için):

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

Çağrı, omp_get_num_threads() kodun seri bölümünde 1 döndürür, bu nedenle np her zaman önceki örnekte 1'e eşit olur. Paralel bölge için dağıtılacak iş parçacığı sayısını belirlemek için çağrının paralel bölge içinde olması gerekir.

Aşağıdaki örnek, iş parçacığı sayısı için bir sorgu eklemeden bu programın nasıl yeniden yazılmasını gösterir:

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

A.16 Kilitler

Aşağıdaki örnekte (bölüm 3.2 için), kilit işlevlerinin bağımsız değişkeninin türü omp_lock_tolmalıdır ve temizlemeye gerek yoktur. Kilit işlevleri, ilk kritik bölüme girişi beklerken iş parçacıklarının boşta kalmalarına, ancak ikinci bölüme girişi beklerken başka işler yapmalarına neden olur. omp_set_lock İşlev bloklar, ancak omp_test_lock işlevi engellemez ve içindeki işin skip() yapılmasına izin verir.

// 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);
}

A.17 İç içe yerleştirilmiş kilitler

Aşağıdaki örnek (bölüm 3.2 için), iç içe bir kilidin güncelleştirmeleri hem tüm yapıya hem de üyelerinden birine eşitlemek için nasıl kullanılabileceğini gösterir.

#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 yönergeleri için iç içe

İç ve dış for yönergeleri farklı paralel bölgelere bağlandığından aşağıdaki yönerge iç içe yerleştirmeuyumludur:

#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);
            }
        }
}

Yukarıdaki örneğin aşağıdaki varyasyonu da uyumludur:

#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;
}

A.19 İş paylaşımı yönergelerinin yanlış iç içe yerleştirilmiş olduğunu gösteren örnekler

Bu bölümdeki örneklerde yönerge iç içe yerleştirme kuralları gösterilmektedir.

aşağıdaki örnek uyumsuzdur çünkü iç ve dış for yönergeleri iç içe ve aynı parallel yönergeye bağlanır:

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);
     }
   }
}

Yukarıdaki örneğin dinamik olarak iç içe yerleştirilmiş aşağıdaki sürümü de uyumsuzdur:

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);
}

Aşağıdaki örnek uyumsuzdur çünkü for ve single yönergeleri iç içe yerleştirilmiştir ve aynı paralel bölgeye bağlanır:

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);
      }
  }
}

aşağıdaki örnek uyumsuzdur çünkü içindeki barrier bir for yönerge kilitlenmeye neden olabilir:

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);
      }
  }
}

Aşağıdaki örnek uyumsuzdur çünkü bir kerede yalnızca bir iş parçacığının barrier kritik bölüme girebileceği için kilitlenmeye neden olur:

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

Aşağıdaki örnek uyumsuzdur çünkü barrier yalnızca bir iş parçacığının bölümü yürütmesi nedeniyle kilitlenmeye neden olur single :

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

A.20 Bind engeli yönergeleri

Yönerge bağlama kuralları, en yakın kapsayan barrier yönergeye bağlanmak için bir parallel yönerge çağırır. Yönerge bağlama hakkında daha fazla bilgi için bkz . bölüm 2.8.

Aşağıdaki örnekte, (alt3'te) alt2'deki paralel bölgeye bağlandığından , main'dan barriersub2'ye yapılan çağrı uyumludur. Subroutine sub2 Ana bölgeden Ayrıca, barrier yalnızca kapsayan paralel bölgedeki iş parçacıkları takımını eşitler ve sub1'de oluşturulan tüm iş parçacıklarını eşitler.

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);
}

Private yan tümcesi ile A.21 Kapsam değişkenleri

Aşağıdaki örnekte ve i değerlerij, paralel bölgeden çıkışta tanımlanmamıştır:

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);

Yan tümcesi private hakkında daha fazla bilgi için bkz . bölüm 2.7.2.1.

A.22 Default(none) yan tümcesi

Aşağıdaki örnek, yan tümcesinden etkilenen default(none) değişkenleri olmayan değişkenlerden ayırır:

// 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
   }
}

Yan tümcesi default hakkında daha fazla bilgi için bkz . bölüm 2.7.2.5.

A.23 Sıralı yönerge örnekleri

Yan tümcesiyle belirtilen for birçok sıralı bölüme ordered sahip olmak mümkündür. API aşağıdaki kuralı belirttiğinden ilk örnek uyumsuzdur:

"Bir yapıya sahip for bir döngü yinelemesi aynı ordered yönergeyi birden çok kez yürütmemeli ve birden ordered fazla yönerge yürütmemelidir." (Bkz . bölüm 2.6.6.)

Bu uyumsuz örnekte, tüm yinelemeler iki sıralı bölüm yürütür:

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

Aşağıdaki uyumlu örnekte birden fazla sıralı bölüm içeren bir for gösterilmektedir:

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

A.24 Özel yan tümce örneği

Paralel bölgenin özel yan tümcesi, bölgenin dinamik kapsamı için değil, yalnızca bölgenin sözcük temelli kapsamı için geçerlidir. Bu nedenle, aşağıdaki örnekte, f yordamındaki döngü içindeki afortüm kullanımları bir özel kopyasına, g yordamındaki bir kullanım ise genel a'ya başvurur.

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 Copyprivate data attribute yan tümcesinin örnekleri

Örnek 1:Copyprivate yan tümcesi, tek bir iş parçacığı tarafından alınan değerleri diğer iş parçacıklarındaki özel değişkenlerin tüm örneklerine doğrudan yayınlamak için kullanılabilir.

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);
}

Rutin başlatma bir seri bölgeden çağrılırsa, davranışı yönergelerin varlığından etkilenmez. get_values yordamına yapılan çağrı bir iş parçacığı tarafından yürütüldükten sonra, tüm iş parçacıklarında a, b, x ve y tarafından belirlenen özel nesneler okunan değerlerle tanımlanana kadar hiçbir iş parçacığı yapısından ayrılmaz.

Örnek 2: Önceki örneğin aksine, okuma işleminin ana iş parçacığı gibi belirli bir iş parçacığı tarafından gerçekleştirilmesi gerektiğini varsayalım. Bu durumda, copyprivate yan tümcesi yayını doğrudan yapmak için kullanılamaz, ancak geçici bir paylaşılan nesneye erişim sağlamak için kullanılabilir.

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;
}

Örnek 3: Paralel bir bölgede gerekli olan kilit nesnelerinin sayısının, girmeden önce kolayca belirleneebileceğini varsayalım. yan tümcesi copyprivate , bu paralel bölge içinde ayrılan paylaşılan kilit nesnelerine erişim sağlamak için kullanılabilir.

#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 Threadprivate yönergesi

Aşağıdaki örneklerde, her iş parçacığına ayrı bir sayaç vermek için threadprivate yönergesinin nasıl kullanılacağı gösterilmektedir.

Örnek 1

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

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

Örnek 2

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

A.27 C99 değişken uzunluklu diziler

Aşağıdaki örnekte, bir firstprivate yönergesinde C99 Değişken Uzunluk Dizilerinin (VLA) nasıl kullanılacağı gösterilmektedir.

Not

Değişken uzunluklu diziler şu anda Visual C++'da desteklenmemektedir.

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

A.28 num_threads yan tümcesi

Aşağıdaki örnekte num_threads yan tümcesi gösterilmektedir. Paralel bölge en fazla 10 iş parçacığıyla yürütülür.

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

A.29 Kritik bir yapı içinde iş paylaşımı yapıları

Aşağıdaki örnekte, bir yapı içinde bir iş paylaşımı yapısının kullanılması gösterilmektedir critical . İş paylaşım yapısı ve critical yapı aynı paralel bölgeye bağlanmadığından bu örnek uyumludur.

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

A.30 Yeniden Özelleştirme

Aşağıdaki örnekte değişkenlerin yeniden özelleştirilmesi gösterilmektedir. Özel değişkenler iç içe yerleştirilmiş bir yönergede yeniden işaretlenebilir private . Bu değişkenleri kapsayan paralel bölgede paylaşmanız gerekmez.

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

A.31 İş parçacığı güvenli kilit işlevleri

Aşağıdaki C++ örneği, omp_init_lock kullanarak paralel bir bölgede kilit dizisi başlatmayı gösterir.

// 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 () {}