Arahan OpenMP

Menyediakan tautan ke arahan yang digunakan dalam API OpenMP.

Visual C++ mendukung arahan OpenMP berikut.

Untuk berbagi kerja paralel:

Direktif Deskripsi
Paralel Mendefinisikan wilayah paralel, yang merupakan kode yang akan dijalankan oleh beberapa utas secara paralel.
Untuk Menyebabkan pekerjaan yang dilakukan dalam perulangan for di dalam wilayah paralel dibagi di antara utas.
Bagian Mengidentifikasi bagian kode yang akan dibagi di antara semua utas.
tunggal Memungkinkan Anda menentukan bahwa bagian kode harus dijalankan pada satu utas, belum tentu utas utama.

Untuk alur utama dan sinkronisasi:

Direktif Deskripsi
master Menentukan bahwa hanya utas utama yang harus menjalankan bagian program.
Kritis Menentukan bahwa kode hanya dijalankan pada satu utas pada satu waktu.
Penghalang Menyinkronkan semua utas dalam tim; semua utas berhenti sejenak di penghubung, sampai semua utas menjalankan penghubung.
Atom Menentukan bahwa lokasi memori yang akan diperbarui secara atomik.
Flush Menentukan bahwa semua utas memiliki tampilan memori yang sama untuk semua objek bersama.
Memerintahkan Menentukan bahwa kode di bawah perulangan paralel for harus dijalankan seperti perulangan berurutan.

Untuk lingkungan data:

Direktif Deskripsi
threadprivate Menentukan bahwa variabel bersifat privat ke utas.

Atom

Menentukan bahwa lokasi memori yang akan diperbarui secara atomik.

#pragma omp atomic
   expression

Parameter

expression
Pernyataan yang memiliki lvalue, yang lokasi memorinya ingin Anda lindungi dari lebih dari satu tulisan.

Keterangan

Direktif atomic tidak mendukung klausa.

Untuk informasi selengkapnya, lihat konstruksi atom 2.6.4.

Contoh

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

#define MAX 10

int main() {
   int count = 0;
   #pragma omp parallel num_threads(MAX)
   {
      #pragma omp atomic
      count++;
   }
   printf_s("Number of threads: %d\n", count);
}
Number of threads: 10

barrier

Menyinkronkan semua utas dalam tim; semua utas berhenti sejenak di penghubung, sampai semua utas menjalankan penghubung.

#pragma omp barrier

Keterangan

Direktif barrier tidak mendukung klausa.

Untuk informasi selengkapnya, lihat Direktif hambatan 2.6.3.

Contoh

Untuk sampel cara menggunakan barrier, lihat master.

critical

Menentukan bahwa kode hanya dijalankan pada satu utas pada satu waktu.

#pragma omp critical [(name)]
{
   code_block
}

Parameter

nama
(Opsional) Nama untuk mengidentifikasi kode penting. Nama harus diapit dalam tanda kurung.

Keterangan

Direktif critical tidak mendukung klausa.

Untuk informasi selengkapnya, lihat konstruksi kritis 2.6.2.

Contoh

// omp_critical.cpp
// compile with: /openmp
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

#define SIZE 10

int main()
{
    int i;
    int max;
    int a[SIZE];

    for (i = 0; i < SIZE; i++)
    {
        a[i] = rand();
        printf_s("%d\n", a[i]);
    }

    max = a[0];
    #pragma omp parallel for num_threads(4)
        for (i = 1; i < SIZE; i++)
        {
            if (a[i] > max)
            {
                #pragma omp critical
                {
                    // compare a[i] and max again because max
                    // could have been changed by another thread after
                    // the comparison outside the critical section
                    if (a[i] > max)
                        max = a[i];
                }
            }
        }

    printf_s("max = %d\n", max);
}
41
18467
6334
26500
19169
15724
11478
29358
26962
24464
max = 29358

Flush

Menentukan bahwa semua utas memiliki tampilan memori yang sama untuk semua objek bersama.

#pragma omp flush [(var)]

Parameter

var
(Opsional) Daftar variabel yang dipisahkan koma yang mewakili objek yang ingin Anda sinkronkan. Jika var tidak ditentukan, semua memori akan dihapus.

Keterangan

Direktif flush tidak mendukung klausa.

Untuk informasi selengkapnya, lihat direktif flush 2.6.5.

Contoh

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

void read(int *data) {
   printf_s("read data\n");
   *data = 1;
}

void process(int *data) {
   printf_s("process data\n");
   (*data)++;
}

int main() {
   int data;
   int flag;

   flag = 0;

   #pragma omp parallel sections num_threads(2)
   {
      #pragma omp section
      {
         printf_s("Thread %d: ", omp_get_thread_num( ));
         read(&data);
         #pragma omp flush(data)
         flag = 1;
         #pragma omp flush(flag)
         // Do more work.
      }

      #pragma omp section
      {
         while (!flag) {
            #pragma omp flush(flag)
         }
         #pragma omp flush(data)

         printf_s("Thread %d: ", omp_get_thread_num( ));
         process(&data);
         printf_s("data = %d\n", data);
      }
   }
}
Thread 0: read data
Thread 1: process data
data = 2

untuk

Menyebabkan pekerjaan yang dilakukan dalam perulangan for di dalam wilayah paralel dibagi di antara utas.

#pragma omp [parallel] for [clauses]
   for_statement

Parameter

Klausul
(Opsional) Nol atau lebih klausa, lihat bagian Komentar .

for_statement
Sebuah for perulangan. Perilaku yang tidak ditentukan akan mengakibatkan jika kode pengguna dalam perulangan for mengubah variabel indeks.

Keterangan

Direktif for mendukung klausul berikut:

Jika parallel juga ditentukan, clauses dapat berupa klausul apa pun yang diterima oleh atau for direktifparallel, kecuali nowait.

Untuk informasi selengkapnya, lihat 2.4.1 untuk konstruksi.

Contoh

// omp_for.cpp
// compile with: /openmp
#include <stdio.h>
#include <math.h>
#include <omp.h>

#define NUM_THREADS 4
#define NUM_START 1
#define NUM_END 10

int main() {
   int i, nRet = 0, nSum = 0, nStart = NUM_START, nEnd = NUM_END;
   int nThreads = 0, nTmp = nStart + nEnd;
   unsigned uTmp = (unsigned((abs(nStart - nEnd) + 1)) *
                               unsigned(abs(nTmp))) / 2;
   int nSumCalc = uTmp;

   if (nTmp < 0)
      nSumCalc = -nSumCalc;

   omp_set_num_threads(NUM_THREADS);

   #pragma omp parallel default(none) private(i) shared(nSum, nThreads, nStart, nEnd)
   {
      #pragma omp master
      nThreads = omp_get_num_threads();

      #pragma omp for
      for (i=nStart; i<=nEnd; ++i) {
            #pragma omp atomic
            nSum += i;
      }
   }

   if  (nThreads == NUM_THREADS) {
      printf_s("%d OpenMP threads were used.\n", NUM_THREADS);
      nRet = 0;
   }
   else {
      printf_s("Expected %d OpenMP threads, but %d were used.\n",
               NUM_THREADS, nThreads);
      nRet = 1;
   }

   if (nSum != nSumCalc) {
      printf_s("The sum of %d through %d should be %d, "
               "but %d was reported!\n",
               NUM_START, NUM_END, nSumCalc, nSum);
      nRet = 1;
   }
   else
      printf_s("The sum of %d through %d is %d\n",
               NUM_START, NUM_END, nSum);
}
4 OpenMP threads were used.
The sum of 1 through 10 is 55

master

Menentukan bahwa hanya utas utama yang harus menjalankan bagian program.

#pragma omp master
{
   code_block
}

Keterangan

Direktif master tidak mendukung klausa.

Untuk informasi selengkapnya, lihat konstruksi master 2.6.1.

Untuk menentukan bahwa bagian kode harus dijalankan pada satu utas, belum tentu utas utama, gunakan direktif tunggal sebagai gantinya.

Contoh

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

int main( )
{
    int a[5], i;

    #pragma omp parallel
    {
        // Perform some computation.
        #pragma omp for
        for (i = 0; i < 5; i++)
            a[i] = i * i;

        // Print intermediate results.
        #pragma omp master
            for (i = 0; i < 5; i++)
                printf_s("a[%d] = %d\n", i, a[i]);

        // Wait.
        #pragma omp barrier

        // Continue with the computation.
        #pragma omp for
        for (i = 0; i < 5; i++)
            a[i] += i;
    }
}
a[0] = 0
a[1] = 1
a[2] = 4
a[3] = 9
a[4] = 16

dipesan

Menentukan bahwa kode di bawah perulangan paralel for harus dijalankan seperti perulangan berurutan.

#pragma omp ordered
   structured-block

Keterangan

Direktif ordered harus berada dalam tingkat dinamis untuk atau parallel for membangun dengan ordered klausul.

Direktif ordered tidak mendukung klausa.

Untuk informasi selengkapnya, lihat konstruksi yang diurutkan 2.6.6.

Contoh

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

static float a[1000], b[1000], c[1000];

void test(int first, int last)
{
    #pragma omp for schedule(static) ordered
    for (int i = first; i <= last; ++i) {
        // Do something here.
        if (i % 2)
        {
            #pragma omp ordered
            printf_s("test() iteration %d\n", i);
        }
    }
}

void test2(int iter)
{
    #pragma omp ordered
    printf_s("test2() iteration %d\n", iter);
}

int main( )
{
    int i;
    #pragma omp parallel
    {
        test(1, 8);
        #pragma omp for ordered
        for (i = 0 ; i < 5 ; i++)
            test2(i);
    }
}
test() iteration 1
test() iteration 3
test() iteration 5
test() iteration 7
test2() iteration 0
test2() iteration 1
test2() iteration 2
test2() iteration 3
test2() iteration 4

parallel

Mendefinisikan wilayah paralel, yang merupakan kode yang akan dijalankan oleh beberapa utas secara paralel.

#pragma omp parallel [clauses]
{
   code_block
}

Parameter

Klausul
(Opsional) Nol atau lebih klausa, lihat bagian Komentar .

Keterangan

Direktif parallel mendukung klausul berikut:

parallel juga dapat digunakan dengan arahan untuk dan bagian .

Untuk informasi selengkapnya, lihat konstruksi paralel 2.3.

Contoh

Contoh berikut menunjukkan cara mengatur jumlah utas dan menentukan wilayah paralel. Jumlah utas sama secara default dengan jumlah prosesor logis pada komputer. Misalnya, jika Anda memiliki mesin dengan satu prosesor fisik yang mengaktifkan hyperthreading, itu akan memiliki dua prosesor logis dan dua utas. Urutan output dapat bervariasi pada komputer yang berbeda.

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

int main() {
   #pragma omp parallel num_threads(4)
   {
      int i = omp_get_thread_num();
      printf_s("Hello from thread %d\n", i);
   }
}
Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3

Bagian

Mengidentifikasi bagian kode yang akan dibagi di antara semua utas.

#pragma omp [parallel] sections [clauses]
{
   #pragma omp section
   {
      code_block
   }
}

Parameter

Klausul
(Opsional) Nol atau lebih klausa, lihat bagian Komentar .

Keterangan

Direktif sections dapat berisi nol atau lebih section direktif.

Direktif sections mendukung klausul berikut:

Jika parallel juga ditentukan, clauses dapat berupa klausul apa pun yang diterima oleh atau sections direktifparallel, kecuali nowait.

Untuk informasi selengkapnya, lihat konstruksi bagian 2.4.2.

Contoh

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

int main() {
    #pragma omp parallel sections num_threads(4)
    {
        printf_s("Hello from thread %d\n", omp_get_thread_num());
        #pragma omp section
        printf_s("Hello from thread %d\n", omp_get_thread_num());
    }
}
Hello from thread 0
Hello from thread 0

tunggal

Memungkinkan Anda menentukan bahwa bagian kode harus dijalankan pada satu utas, belum tentu utas utama.

#pragma omp single [clauses]
{
   code_block
}

Parameter

Klausul
(Opsional) Nol atau lebih klausa, lihat bagian Komentar .

Keterangan

Direktif single mendukung klausul berikut:

Untuk informasi selengkapnya, lihat konstruksi tunggal 2.4.3.

Untuk menentukan bahwa bagian kode hanya boleh dijalankan pada utas utama, gunakan arahan master sebagai gantinya.

Contoh

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

int main() {
   #pragma omp parallel num_threads(2)
   {
      #pragma omp single
      // Only a single thread can read the input.
      printf_s("read input\n");

      // Multiple threads in the team compute the results.
      printf_s("compute results\n");

      #pragma omp single
      // Only a single thread can write the output.
      printf_s("write output\n");
    }
}
read input
compute results
compute results
write output

threadprivate

Menentukan bahwa variabel bersifat privat ke utas.

#pragma omp threadprivate(var)

Parameter

var
Daftar variabel yang dipisahkan koma yang ingin Anda jadikan privat ke utas. var harus berupa variabel cakupan global atau namespace atau variabel statis lokal.

Keterangan

Direktif threadprivate tidak mendukung klausa.

Arahan didasarkan pada atribut utas menggunakan kata kunci __declspec; batasan __declspec(thread) berlaku untuk threadprivate.threadprivate Misalnya, threadprivate variabel akan ada di utas apa pun yang dimulai dalam proses, bukan hanya utas yang merupakan bagian dari tim utas yang dihasilkan oleh wilayah paralel. Perhatikan detail implementasi ini; Anda mungkin melihat bahwa konstruktor untuk jenis yang threadprivate ditentukan pengguna disebut lebih sering kemudian diharapkan.

Anda dapat menggunakan threadprivate dalam DLL yang dimuat secara statis saat startup proses, namun Anda tidak dapat menggunakan threadprivate di DLL apa pun yang akan dimuat melalui LoadLibrary seperti DLL yang dimuat dengan /DELAYLOAD (impor beban penundaan), yang juga menggunakan LoadLibrary.

threadprivate Variabel jenis yang dapat dihancurkan tidak dijamin memiliki destruktor yang dipanggil. Contohnya:

struct MyType
{
    ~MyType();
};

MyType threaded_var;
#pragma omp threadprivate(threaded_var)
int main()
{
    #pragma omp parallel
    {}
}

Pengguna tidak memiliki kontrol kapan utas yang merupakan wilayah paralel akan berakhir. Jika utas tersebut ada ketika proses keluar, utas tidak akan diberi tahu tentang proses keluar, dan destruktor tidak akan dipanggil untuk threaded_var pada utas apa pun kecuali yang keluar (di sini, utas utama). Jadi kode tidak boleh mengandalkan threadprivate penghancuran variabel yang tepat.

Untuk informasi selengkapnya, lihat direktif threadprivate 2.7.1.

Contoh

Untuk sampel penggunaan threadprivate, lihat privat.