it-swarm-id.com

Apa perbedaan antara atomik dan kritis dalam OpenMP?

Apa perbedaan antara atomik dan kritis dalam OpenMP?

Aku bisa melakukan ini

#pragma omp atomic
g_qCount++;

tetapi tidak sama dengan ini

#pragma omp critical
g_qCount++;

?

Efeknya pada g_qCount sama, tetapi apa yang dilakukan berbeda.

Bagian kritis OpenMP sepenuhnya umum - ia dapat mengelilingi setiap blok kode yang berubah-ubah. Anda membayar untuk generalitas itu, bagaimanapun, dengan mengeluarkan overhead yang signifikan setiap kali sebuah thread masuk dan keluar dari bagian kritis (di atas biaya inheren serialisasi).

(Selain itu, dalam OpenMP semua bagian penting yang tidak disebutkan namanya dianggap identik (jika Anda mau, hanya ada satu kunci untuk semua bagian penting yang tidak disebutkan namanya), sehingga jika satu utas berada dalam satu bagian kritis [tidak dinamai] seperti di atas, tidak ada utas yang dapat memasukkan apa pun Bagian kritis [tidak disebutkan namanya] Seperti yang Anda duga, Anda dapat menyiasatinya dengan menggunakan bagian kritis yang bernama).

Operasi atom memiliki overhead yang jauh lebih rendah. Jika tersedia, perangkat ini memanfaatkan perangkat keras yang menyediakan (misalnya) operasi penambahan atom; dalam hal itu tidak ada kunci/buka kunci yang diperlukan untuk memasukkan/keluar dari baris kode, itu hanya melakukan penambahan atom yang perangkat keras memberitahu Anda tidak dapat diganggu.

Sisi baiknya adalah bahwa overhead jauh lebih rendah, dan satu thread berada dalam operasi atom tidak menghalangi operasi atom (berbeda) yang akan terjadi. Kelemahannya adalah serangkaian operasi terbatas yang didukung oleh atom.

Tentu saja, dalam kedua kasus tersebut, Anda harus mengeluarkan biaya serialisasi.

158
Jonathan Dursi

Dalam OpenMP, semua bagian kritis yang tidak disebutkan namanya adalah saling eksklusif.

Perbedaan paling penting antara kritis dan atom adalah bahwa atom hanya dapat melindungi satu tugas dan Anda dapat menggunakannya dengan operator tertentu.

27
Michael

bagian kritis:

  • Memastikan serialisasi blok kode.
  • Dapat diperluas ke kelompok serialisasi blok dengan penggunaan tag "nama" yang tepat.

  • Lebih lambat!

Operasi atom:

  • Jauh lebih cepat!

  • Hanya memastikan serialisasi operasi tertentu.

15
efarsarakis

Cara tercepat bukanlah hal yang kritis maupun atomik. Kira-kira, penambahan dengan bagian kritis adalah 200 kali lebih mahal dari penambahan sederhana, penambahan atom adalah 25 kali lebih mahal dari penambahan sederhana.

Opsi tercepat (tidak selalu berlaku) adalah memberikan masing-masing utas penghitungnya sendiri dan melakukan pengurangan operasi ketika Anda membutuhkan jumlah total.

7
Andrii

Batasan atomic adalah penting. Mereka harus dirinci pada spesifikasi OpenMP . MSDN menawarkan lembar cheat cepat karena saya tidak akan terkejut jika ini tidak akan berubah. (Visual Studio 2012 memiliki implementasi OpenMP dari Maret 2002.) Mengutip MSDN:

Pernyataan ekspresi harus memiliki salah satu dari bentuk berikut:

x binop = expr

x++

++x

x--

--x

Dalam ekspresi sebelumnya: x adalah ekspresi lvalue dengan tipe skalar. expr adalah ekspresi dengan tipe skalar, dan itu tidak merujuk objek yang ditunjuk oleh x. binop bukan operator kelebihan beban dan merupakan salah satu dari +, *, -, /, &, ^, |, <<, atau >>.

Saya sarankan untuk menggunakan atomic ketika Anda bisa dan bernama bagian penting sebaliknya. Memberi mereka nama itu penting; Anda akan menghindari men-debug sakit kepala dengan cara ini.

5
darda

Penjelasannya sudah bagus di sini. Namun, kita bisa menyelam sedikit lebih dalam. Untuk memahami perbedaan inti antara atomic dan bagian kritis konsep dalam OpenMP , kita harus memahami konsep kunci terlebih dahulu. Mari kita tinjau mengapa kita perlu menggunakan kunci .

Program paralel sedang dijalankan oleh banyak utas. Hasil deterministik akan terjadi jika dan hanya jika kami melakukan sinkronisasi di antara utas ini. Tentu saja, sinkronisasi antara utas tidak selalu diperlukan. Kami merujuk pada kasus-kasus itu yang memerlukan sinkronisasi .

Untuk menyinkronkan utas dalam program multi-utas, kami akan menggunakan kunci. Ketika akses harus dibatasi hanya oleh satu utas pada satu waktu, kunci s ikut bermain. The kunci implementasi konsep dapat bervariasi dari prosesor ke prosesor. Mari kita cari tahu bagaimana kunci sederhana dapat bekerja dari sudut pandang algoritmik.

1. Define a variable called lock.
2. For each thread:
   2.1. Read the lock.
   2.2. If lock == 0, lock = 1 and goto 3    // Try to grab the lock
       Else goto 2.1    // Wait until the lock is released
3. Do something...
4. lock = 0    // Release the lock

Algoritma yang diberikan dapat diimplementasikan dalam bahasa perangkat keras sebagai berikut. Kami akan mengasumsikan prosesor tunggal dan menganalisis perilaku kunci itu. Untuk latihan ini, mari kita asumsikan salah satu dari prosesor berikut: MIPS , Alpha, LENGAN atau Power.

try:    LW R1, lock
        BNEZ R1, try
        ADDI R1, R1, #1
        SW R1, lock

Program ini tampaknya baik-baik saja, tetapi tidak. Kode di atas menderita masalah sebelumnya; sinkronisasi . Mari kita temukan masalahnya. Asumsikan nilai awal kunci menjadi nol. Jika dua utas menjalankan kode ini, satu dapat mencapai SW R1, mengunci sebelum yang lain membaca kunci variabel. Dengan demikian, keduanya berpikir bahwa kunci gratis. Untuk mengatasi masalah ini, ada instruksi lain yang disediakan daripada sederhana [~ # ~] lw [~ # ~] dan [~ # ~] sw [~ # ~] . Ini disebut instruksi Read-Modify-Write . Ini adalah instruksi yang kompleks (terdiri dari subinstructions) yang menjamin prosedur akuisisi kunci dilakukan hanya oleh utas tunggal pada suatu waktu. Perbedaan Baca-Ubah-Tulis dibandingkan dengan yang sederhana Baca dan Tulis instruksi adalah bahwa ia menggunakan cara yang berbeda dari Memuat dan Menyimpan . Ia menggunakan [~ # ~] ll [~ # ~] (Muat Tertaut) untuk memuat variabel kunci dan [~ # ~] sc [~ # ~] (Simpan Bersyarat) untuk menulis ke variabel kunci. Tambahan Daftar Tautan digunakan untuk memastikan prosedur akuisisi kunci dilakukan oleh satu utas. Algoritma diberikan di bawah ini.

1. Define a variable called lock.
2. For each thread:
   2.1. Read the lock and put the address of lock variable inside the Link Register.
   2.2. If (lock == 0) and (&lock == Link Register), lock = 1 and reset the Link Register then goto 3    // Try to grab the lock
       Else goto 2.1    // Wait until the lock is released
3. Do something...
4. lock = 0    // Release the lock

Ketika register tautan direset, jika utas lain menganggap kunci itu gratis, maka tidak akan bisa lagi menulis nilai yang ditambahkan ke kunci. Dengan demikian, konkurensi akses ke variabel kunci diperoleh.

Perbedaan inti antara critical dan atomic berasal dari gagasan bahwa:

Mengapa menggunakan kunci (variabel baru) sementara kita bisa menggunakan variabel aktual (yang sedang kita lakukan operasi di atasnya), sebagai variabel kunci?

Menggunakan bar variabel untuk kunci akan mengarah ke bagian kritis, saat menggunakan variabel aktual sebagai kunci akan mengarah to atomic konsep. Bagian kritis berguna ketika kita melakukan banyak perhitungan (lebih dari satu baris) pada variabel aktual. Itu karena, jika hasil perhitungan tersebut gagal ditulis pada variabel aktual, seluruh prosedur harus diulang untuk menghitung hasilnya. Ini dapat menyebabkan kinerja yang buruk dibandingkan dengan menunggu kunci untuk dirilis sebelum memasuki wilayah yang sangat komputasi. Dengan demikian, disarankan untuk menggunakan direktif atom setiap kali Anda ingin melakukan perhitungan tunggal (x ++, x--, ++ x, --x , dll.) dan gunakan petunjuk kritis ketika wilayah yang lebih kompleks secara komputasional dilakukan oleh bagian intensif.

1
hexpheus