OpenMP Yan Tümceleri

OpenMP API'sinde kullanılan yan tümcelere bağlantılar sağlar.

Visual C++ aşağıdaki OpenMP yan tümcelerini destekler.

Genel öznitelikler için:

Yan Tümce Açıklama
eğer Bir döngünün paralel mi yoksa seri olarak mı yürütülmesi gerektiğini belirtir.
num_threads bir iş parçacığı ekibindeki iş parçacığı sayısını ayarlar.
Sipariş Döngüde bir sıralı yönerge kullanılacaksa deyimi için paralel olarak gereklidir.
schedule for yönergesi için geçerlidir.
nowait Bir yönergedeki örtük engeli geçersiz kılar.

Veri paylaşımı öznitelikleri için:

Yan Tümce Açıklama
private Her iş parçacığının kendi değişken örneğine sahip olması gerektiğini belirtir.
firstprivate Her iş parçacığının kendi değişken örneğine sahip olması gerektiğini ve değişkenin paralel yapıdan önce mevcut olduğundan değişkenin değeriyle başlatılması gerektiğini belirtir.
lastprivate Değişkeni kapsayan bağlamın sürümünün, son yinelemeyi (for-döngü yapısı) veya son bölümü (#pragma bölümleri) yürüten iş parçacığının özel sürümüne eşit olarak ayarlandığını belirtir.
Paylaşılan Bir veya daha fazla değişkenin tüm iş parçacıkları arasında paylaşılması gerektiğini belirtir.
varsayılan Paralel bir bölgede kapsamsız değişkenlerin davranışını belirtir.
reduction Her iş parçacığı için özel olan bir veya daha fazla değişkenin paralel bölgenin sonundaki bir azaltma işleminin konusu olduğunu belirtir.
copyin İş parçacıklarının bir threadprivate değişkeni için ana iş parçacığının değerine erişmesine izin verir.
copyprivate Bir veya daha fazla değişkenin tüm iş parçacıkları arasında paylaşılması gerektiğini belirtir.

copyin

İş parçacıklarının bir threadprivate değişkeni için ana iş parçacığının değerine erişmesine izin verir.

copyin(var)

Parametreler

var
Paralel threadprivate yapıdan önce mevcut olduğundan, değişkenin ana iş parçacığındaki değeriyle başlatılacak değişken.

Açıklamalar

copyin aşağıdaki yönergeler için geçerlidir:

Daha fazla bilgi için bkz . 2.7.2.7 copyin.

Örnek

kullanma copyinörneği için bkz. threadprivate.

copyprivate

Bir veya daha fazla değişkenin tüm iş parçacıkları arasında paylaşılması gerektiğini belirtir.

copyprivate(var)

Parametreler

var
Paylaşacak bir veya daha fazla değişken. Birden fazla değişken belirtilirse, değişken adlarını virgülle ayırın.

Açıklamalar

copyprivatetek yönerge için geçerlidir.

Daha fazla bilgi için bkz . 2.7.2.8 copyprivate.

Örnek

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

varsayılan

Paralel bir bölgede kapsamsız değişkenlerin davranışını belirtir.

default(shared | none)

Açıklamalar

shared, yan tümcesi default belirtilmemişse etkindir, paralel bölgedeki herhangi bir değişkenin paylaşılan yan tümcesi ile belirtilmiş gibi davranılacağı anlamına gelir. noneözel, paylaşılan, azaltma, firstprivate veya lastprivate yan tümcesiyle kapsamı belirlenmiş olmayan paralel bölgede kullanılan tüm değişkenlerin derleyici hatasına neden olacağı anlamına gelir.

default aşağıdaki yönergeler için geçerlidir:

Daha fazla bilgi için bkz . 2.7.2.5 varsayılanı.

Örnek

kullanma defaultörneği için bkz. private.

firstprivate

Her iş parçacığının kendi değişken örneğine sahip olması gerektiğini ve değişkenin paralel yapıdan önce mevcut olduğundan değişkenin değeriyle başlatılması gerektiğini belirtir.

firstprivate(var)

Parametreler

var
Her iş parçacığında örnekleri olan ve paralel yapıdan önce var olduğundan değişkenin değeriyle başlatılacak değişkeni. Birden fazla değişken belirtilirse, değişken adlarını virgülle ayırın.

Açıklamalar

firstprivate aşağıdaki yönergeler için geçerlidir:

Daha fazla bilgi için bkz . 2.7.2.2 firstprivate.

Örnek

kullanma firstprivateörneği için bkz. private içindeki örnek.

if (OpenMP)

Bir döngünün paralel mi yoksa seri olarak mı yürütülmesi gerektiğini belirtir.

if(expression)

Parametreler

ifade
True (sıfır olmayan) olarak değerlendirilirse paralel bölgedeki kodun paralel olarak yürütülmesine neden olan bir integral ifadesi. İfade false (sıfır) olarak değerlendirilirse, paralel bölge seri olarak (tek bir iş parçacığı tarafından) yürütülür.

Açıklamalar

if aşağıdaki yönergeler için geçerlidir:

Daha fazla bilgi için bkz . 2.3 paralel yapısı.

Örnek

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

Değişkeni kapsayan bağlamın sürümünün, son yinelemeyi (for-döngü yapısı) veya son bölümü (#pragma bölümleri) yürüten iş parçacığının özel sürümüne eşit olarak ayarlandığını belirtir.

lastprivate(var)

Parametreler

var
İş parçacığının son yinelemeyi (döngü yapısı) veya son bölümü (#pragma bölümleri) yürüten özel sürümüne eşit olarak ayarlanan değişken.

Açıklamalar

lastprivate aşağıdaki yönergeler için geçerlidir:

Daha fazla bilgi için bkz . 2.7.2.3 lastprivate.

Örnek

Kullanım lastprivate yan tümcesi örneği için bkz. zamanlama.

nowait

Bir yönergedeki örtük engeli geçersiz kılar.

nowait

Açıklamalar

nowait aşağıdaki yönergeler için geçerlidir:

Daha fazla bilgi için bkz . yapı için 2.4.1, 2.4.2 bölüm yapısı ve 2.4.3 tek yapı.

Örnek

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

bir iş parçacığı ekibindeki iş parçacığı sayısını ayarlar.

num_threads(num)

Parametreler

Num
İş parçacığı sayısı

Açıklamalar

num_threads yan tümcesi, omp_set_num_threads işleviyle aynı işlevselliğe sahiptir.

num_threads aşağıdaki yönergeler için geçerlidir:

Daha fazla bilgi için bkz . 2.3 paralel yapısı.

Örnek

Yan tümcesi kullanma num_threads örneği için bkz. paralel.

ordered

Döngüde bir sıralı yönerge kullanılacaksa deyimi için paralel olarak gereklidir.

ordered

Açıklamalar

ordered for yönergesi için geçerlidir.

Daha fazla bilgi için bkz . yapı için 2.4.1.

Örnek

Kullanım ordered yan tümcesi örneği için bkz. sıralı.

private

Her iş parçacığının kendi değişken örneğine sahip olması gerektiğini belirtir.

private(var)

Parametreler

var
Her iş parçacığında örneklerin olması için değişken.

Açıklamalar

private aşağıdaki yönergeler için geçerlidir:

Daha fazla bilgi için bkz . 2.7.2.1 özel.

Örnek

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

reduction

Her iş parçacığı için özel olan bir veya daha fazla değişkenin paralel bölgenin sonundaki bir azaltma işleminin konusu olduğunu belirtir.

reduction(operation:var)

Parametreler

işlem
Değişkenler üzerinde yapılacak işlemin işleci, paralel bölgenin sonunda vardır .

var
Skaler azaltmanın gerçekleştirildiği bir veya daha fazla değişken. Birden fazla değişken belirtilirse, değişken adlarını virgülle ayırın.

Açıklamalar

reduction aşağıdaki yönergeler için geçerlidir:

Daha fazla bilgi için bkz . 2.7.2.6 azaltma.

Örnek

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

planla

for yönergesi için geçerlidir.

schedule(type[,size])

Parametreler

type
, guided, runtimeveya staticzamanlama dynamictürü.

boyut
(İsteğe bağlı) Yinelemelerin boyutunu belirtir. boyutu bir tamsayı olmalıdır. türü olduğunda runtimegeçerli değil.

Açıklamalar

Daha fazla bilgi için bkz . yapı için 2.4.1.

Örnek

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

shared

Bir veya daha fazla değişkenin tüm iş parçacıkları arasında paylaşılması gerektiğini belirtir.

shared(var)

Parametreler

var
Paylaşacak bir veya daha fazla değişken. Birden fazla değişken belirtilirse, değişken adlarını virgülle ayırın.

Açıklamalar

Değişkenleri iş parçacıkları arasında paylaşmanın bir diğer yolu da copyprivate yan tümcesidir.

shared aşağıdaki yönergeler için geçerlidir:

Daha fazla bilgi için bkz . 2.7.2.4 shared.

Örnek

kullanma sharedörneği için bkz. private.