2016-04-05 16 views
1

Belirli koşullara bağlı olarak 4 farklı değerin depolanması gereken küçültülmüş kümülatif bir hesaplama yapmaya çalışıyorum. Çekirdeğim uzun dizileri girdi olarak alıyor ve girdideki her veri noktasından elde edilen "global toplam" olan sadece 4 değeri depolaması gerekiyor. Örneğin, belirli koşulu karşılayan tüm veri değerlerinin toplamını ve söz konusu durumla tatmin olan veri noktalarının sayısını kaydetmem gerekiyor. çekirdekte bildirilmediOpenCL: sonuçları aynı genel bellek adresine kaydetme

__kernel void photometry(__global float* stamp, 
         __constant float* dark, 
         __global float* output) 
{ 
int x = get_global_id(0); 
int s = n * n; 

if(x < s){ 
    float2 curr_px = (float2)((x/n), (x % n)); 
    float2 center = (float2)(centerX, centerY); 
    int dist = (int)fast_distance(center, curr_px); 
    if(dist < aperture){ 
     output[0] += stamp[x]-dark[x]; 
     output[1]++; 
    }else if (dist > sky_inner && dist < sky_outer){ 
     output[2] += stamp[x]-dark[x]; 
     output[3]++; 
    } 
} 
} 

tüm değerler daha önce makrolar tarafından tanımlanmıştır: çekirdek daha anlaşılabilir olması için altındadır. s, 1 D'ye kadar düzleştirilmiş n x n ve dark giriş dizilerinin uzunluğudur.

Sonuçları alıyorum, ancak bunun CPU sürümümden farklılar. Tabii ki merak ediyorum: , yapmaya çalıştığım şeyi yapmanın doğru yolu bu mu? Her piksel verisinin sadece bir kez eklendiğinden emin olabilir miyim? Kümülatif sonuç değerlerini kaydetmek için başka bir yol düşünemiyorum.

+0

Birden çok konu aynı dizine eklenmiş öğeleri değiştirmeye çalışıyor. Onlara atomik erişime ihtiyacın var. Atomik ekleme ve atomik artış talimatları. Yani tüm thread'ler tanımsız değerler yerine güncellenmiş değerler alacak. https://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/atomicFunctions.html –

+0

@huseyintugrulbuyukisik öneriniz için teşekkür ederiz. Ancak, iş parçacığı çıktı arabelleği okumayan bile olsa bu gerekli olur mu? İpliklerin okuduğu tamponlar hesaplamada değiştirilmez – Francisca

cevap

3

Durumunuzda atomik işlem gereklidir, aksi halde veri yarışları sonuçların tahmin edilememesine neden olur.

sorun

buradadır: Bu nedenle, aynı dalga içindeki parçacıkları için Tamam olabilir, aynı dalgada ipler hala aynı adımı izleyin olabileceğini tahmin edebilirsiniz

output[0] += stamp[x]-dark[x]; 
output[1]++; 

. Aynı çıkış [0] değerini global yük talimatı (yayın) kullanarak okuduğundan beri. Daha sonra, hesaplamayı bitirdikten sonra ve verileri aynı bellek adresine (çıktı [0]) depolamaya çalıştıklarında, yazma işlemleri serileştirilir. Bu noktada, yine de doğru sonuçları alabilirsiniz (aynı dalga içindeki iş öğeleri için). Ancak, programınızın birden fazla dalga başlatması büyük olasılıkla olduğu için (çoğu uygulamada bu durum geçerlidir). Farklı dalgalar bilinmeyen bir düzende yürütülebilir; Daha sonra, aynı hafıza adresine eriştiğinde, davranış daha karmaşık hale gelir. Örneğin, wave0 ve wave1, herhangi bir başka hesaplama yapılmadan önce çıkışa [0] erişebilir, yani aynı değeri çıktı [0] 'dan alırlar; sonra hesaplamaya başlarlar. Hesaplamadan sonra birikmiş sonuçları çıktıya kaydederler [0]; görünüşe göre, dalgalardan birinin sonucu bir başkasının üzerine yazılacak, sanki sadece bellek yazan kişi idam edildi. Sadece gerçek bir uygulamada çok fazla dalga olduğunu düşünün, bu yüzden yanlış bir sonuca sahip olmak garip değil.

İlgili konular