OpenMP'de atomik ve kritik arasındaki fark nedir?
bunu yapabilirim
#pragma omp atomic
g_qCount++;
ama bu aynı değil mi
#pragma omp critical
g_qCount++;
?
OpenMP'de atomik ve kritik arasındaki fark nedir?
bunu yapabilirim
#pragma omp atomic
g_qCount++;
ama bu aynı değil mi
#pragma omp critical
g_qCount++;
?
Yanıtlar:
G_qCount üzerindeki etki aynıdır, ancak yapılan farklıdır.
Bir OpenMP kritik bölümü tamamen geneldir - herhangi bir rastgele kod bloğunu çevreleyebilir. Bununla birlikte, bir iş parçacığı kritik bölüme her girdiğinde ve çıktığında (serileştirmenin doğal maliyetine ek olarak) önemli bir ek yüke neden olarak bu genellik için ödeme yaparsınız.
(Ek olarak, OpenMP'de tüm adlandırılmamış kritik bölümler aynı kabul edilir (tercih ederseniz, tüm adlandırılmamış kritik bölümler için yalnızca bir kilit vardır), böylece bir iş parçacığı yukarıdaki gibi [adsız] bir kritik bölümdeyse, hiçbir iş parçacığı girilemez. [isimsiz] kritik bölüm Tahmin edebileceğiniz gibi, adlandırılmış kritik bölümleri kullanarak bu sorunu aşabilirsiniz).
Atomik bir operasyon çok daha düşük ek yüke sahiptir. Mümkün olduğunda, (diyelim ki) bir atomik artış işlemi sağlayan donanımdan yararlanır; bu durumda kod satırına girerken / çıkarken kilit / kilit açma gerekmez, sadece donanımın size müdahale edilemeyeceğini söylediği atomik artışı yapar.
Artıları, ek yükün çok daha düşük olması ve atomik bir işlemde olan bir iş parçacığının gerçekleşmek üzere olan (farklı) atomik işlemleri engellememesidir. Olumsuz tarafı, atomiklerin desteklediği kısıtlı işlemler dizisidir.
Elbette, her iki durumda da, serileştirme maliyetini üstlenirsiniz.
Kritik Bölüm:
Doğru "ad" etiketi kullanımıyla blok gruplarını serileştirmek için genişletilebilir.
Yavaş!
Atomik işlem:
Çok daha hızlı!
Yalnızca belirli bir işlemin serileştirilmesini sağlar.
En hızlı yol ne kritik ne de atomiktir. Yaklaşık olarak, kritik bölümlü ekleme, basit eklemeye göre 200 kat, atomik ekleme, basit eklemeye göre 25 kat daha pahalıdır.
En hızlı seçenek (her zaman geçerli değildir), her bir iş parçacığına kendi sayacını vermek ve toplam toplama ihtiyacınız olduğunda azaltma işlemi yapmaktır.
Sınırlamaları atomic
önemlidir. OpenMP özelliklerinde ayrıntılı olarak belirtilmelidirler . MSDN hızlı bir kopya sayfası sunuyor, çünkü bu değişmezse şaşırmam. (Visual Studio 2012, Mart 2002'den itibaren bir OpenMP uygulamasına sahiptir.) MSDN'den alıntı yapmak için:
İfade ifadesi aşağıdaki biçimlerden birine sahip olmalıdır:
x
binop =expr
x++
++x
x--
--x
Önceki ifadelerde: skaler tipte
x
birlvalue
ifadedir.expr
skaler tipte bir ifadedir ve tarafından belirtilen nesneye başvurmazx
. binop aşırı yüklenmiş bir operatör değildir ve biri+
,*
,-
,/
,&
,^
,|
,<<
, ya da>>
.
Aksi takdirde kritik bölümleri atomic
kullanabileceğiniz ve adlandırabileceğiniz durumlarda kullanmanızı öneririm . Bunları adlandırmak önemlidir; Bu şekilde baş ağrılarında hata ayıklamaktan kaçınacaksınız.
Zaten burada harika açıklamalar. Ancak biraz daha derine dalabiliriz. OpenMP'deki atomik ve kritik bölüm kavramları arasındaki temel farkı anlamak için önce kilit kavramını anlamalıyız . Neden kilit kullanmamız gerektiğini gözden geçirelim .
Paralel bir program, birden çok iş parçacığı tarafından yürütülüyor. Deterministik sonuçlar ancak ve ancak bu iş parçacıkları arasında senkronizasyon gerçekleştirirsek gerçekleşir . Elbette, iş parçacıkları arasında senkronizasyon her zaman gerekli değildir. Senkronizasyonun gerekli olduğu durumlara atıfta bulunuyoruz .
Çok evreli bir programda iş parçacıklarını senkronize etmek için kilit kullanacağız . Erişimin bir seferde yalnızca bir iş parçacığı ile sınırlandırılması gerektiğinde, kilit devreye girer. Kilit kavramı uygulama işlemcisinden işlemciye değişebilir. Algoritmik bir bakış açısından basit bir kilidin nasıl çalıştığını öğrenelim.
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
Verilen algoritma, aşağıdaki gibi donanım dilinde uygulanabilir. Tek bir işlemci varsayacağız ve buradaki kilitlerin davranışını analiz edeceğiz. Bu uygulama için aşağıdaki işlemcilerden birini varsayalım: MIPS , Alpha , ARM veya Power .
try: LW R1, lock
BNEZ R1, try
ADDI R1, R1, #1
SW R1, lock
Bu program iyi görünüyor, ama değil. Yukarıdaki kod önceki sorundan muzdariptir; senkronizasyon . Sorunu bulalım. Kilidin başlangıç değerinin sıfır olduğunu varsayın. Eğer iki iş parçacığı bu kodu çalıştırırsa, biri SW R1'e ulaşabilir , diğeri kilit değişkenini okumadan önce kilitlenebilir . Böylece ikisi de kilidin serbest olduğunu düşünüyor . Bu sorunu çözmek için, basit LW ve SW yerine sağlanan başka bir talimat vardır . Oku-Değiştir-Yaz talimatı olarak adlandırılır . Bir seferde kilit edinme prosedürü sadece yapılır tek ipliğini garanti eden karmaşık bir talimattır (alt talimatlardan oluşur) . Farkı Oku-Değiştirme-yazmaBasit Okuma ve Yazma talimatlarıyla karşılaştırıldığında , Yükleme ve Saklama için farklı bir yol kullanmasıdır . Kullandığı LL kilit değişken ve yük (Bağlantılı Load) SC kilit değişkenine yazma için (Mağaza Koşullu). Kilit edinme prosedürünün tek bir iş parçacığı tarafından yapılmasını sağlamak için ek bir Bağlantı Kaydı kullanılır. Algoritma aşağıda verilmiştir.
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
Bağlantı kaydı sıfırlandığında, başka bir iş parçacığı kilidin serbest olduğunu varsayarsa, artan değeri kilide tekrar yazamaz. Böylece, kilide erişimin eşzamanlılığı değişkenine elde edilir.
Kritik ve atomik arasındaki temel fark şu fikrinden gelir:
Asıl değişkeni (üzerinde bir işlem yapıyoruz) kilit değişkeni olarak kullanırken neden kilitleri (yeni bir değişken) kullanalım?
Kilitler için yeni bir değişken kullanmak kritik bölüme yol açarken, gerçek değişkeni kilit olarak kullanmak atomik konsepte yol açacaktır . Kritik bölüm, gerçek değişken üzerinde çok sayıda hesaplama yaptığımızda (birden fazla satır) kullanışlıdır. Bunun nedeni, bu hesaplamaların sonucu gerçek değişken üzerine yazılamazsa, sonuçları hesaplamak için tüm prosedürün tekrarlanması gerekir. Bu, yüksek hesaplamalı bir bölgeye girmeden önce kilidin serbest bırakılmasını beklemeye kıyasla zayıf bir performansa yol açabilir. Bu nedenle, tek bir hesaplama (x ++, x--, ++ x, --x, vb.) Yapmak istediğinizde atom direktifini kullanmanız veyoğun bölüm tarafından hesaplama açısından daha karmaşık bir bölge yapıldığında kritik yönerge.
Yalnızca tek bir talimat için karşılıklı dışlamayı etkinleştirmeniz gerektiğinde atomik göreceli olarak performans açısından verimlidir, benzer omp kritik için doğru değildir.
atomic tek bir ifadedir Kritik bölüm, yani bir ifade yürütme için kilitliyorsunuz
kritik bölüm bir kod bloğu üzerindeki kilittir
İyi bir derleyici, ikinci kodunuzu ilkiyle aynı şekilde çevirecektir.
++
ve*=
) ve donanım desteklemediği durumda, bunlar yerine olabileceğinicritical
bölümler.