2015-12-25 38 views
9

Veri içeren x [] dizilim var. Ayrıca bir dizi "sistem durumu" c []. işlem:Senkron Paralel Süreci C#/C++

for(i = 1; i < N; i++) 
{ 
    a = f1(x[i] + c[i-1]); 
    b = f2(x[i] + c[i-1]); 
    c[i] = a + b; 
} 

2 paralel iplikler kullanılarak 2-çekirdek sisteminde f1 ve f2 değerlerini bulmak için herhangi bir etkili bir yolu var mı?

thread_1 
{ 
    for(i = 1; i < N; i++) 
     a = f1(x[i] + c[i-1]);  
} 
thread_2 
{ 
    for(i = 1; i < N; i++) 
    { 
     b = f2(x[i] + c[i-1]); 
     c[i] = a + b; //here we somehow get a{i} from thread_1 
    } 
} 

f1 ve f2 zaman tüketim değildir, ancak birçok kez hesaplanır gerekir, bu yüzden, istenen hızlanma x2 hakkındadır: I (sözde kodu) şu anlama gelir. grafiksel gösterimi için şemasına bakın:

desired parallel process

Windows için kod örnekleri arıyorum. Seni doğru anladıysam

+1

Sadece f1 ve f2 çok havy ve syncronization overhead paralel koşunun kârı daha az olacak eğer verimli olacak – gabba

+0

Bu neden C# ve ** C++ etiketlendi? Hangi dili kullanıyorsunuz? –

+0

Dil seçimi, görevi daha verimli bir şekilde çözebilecek öğeye göre değişir – carimus

cevap

4

,

    c[i-1] kullanılabilir olduğunda a[i] sadece hesaplanabilir
  • c[i-1] kullanılabilir a[i] ve b[i] hesaplandığı zaman
  • c[i] yalnızca kullanılabilir olduğunda b[i] sadece hesaplanabilir

Ayrı ayrı yapabileceğiniz tek işlemin a[i] ve b[i] hesaplamalarıdır.

Ben C# aynı düşüncelere sahibiz:

for (int i = 1; i < N; i++) 
{ 
    Task<double> calcA = Task.Factory.StartNew(() => { return f1(x[i] + c[i-1]); }); 
    Task<double> calcB = Task.Factory.StartNew(() => { return f2(x[i] + c[i-1]); }); 

    // .Result will block the execution and wait for both calculations to complete 
    c[i] = calcA.Result + calcB.Result; 
} 

Bu sırasıyla f1 ve f2 hesaplar iki ayrı konuları, çalışacaktır. Hem f1 hem de f2 hesaplandıktan sonra, c[i] değerini ayarlayacak ve sonraki yinelemeyi çalıştıracaktır.

  • Sana bazı ilk a[0] ve b[0] değerlere sahip olduğunu varsayarak, sizin f1 ve f2 dönüş double
  • döngü 1'den başlar varsayarak double kullanın: o

    Not. f1 ve f2 hesaplanması gerçekten Aksi takdirde, c[i-1] (Thread kullanarak aksine) ThreadPool'da kullanan diğer hesaplamalar

  • Task.Factory.StartNew
  • kıyasla kaynak tüketen ve uzun o kokan yani bu sadece iyileşme getirecek bir istisna
  • atardı Her seferinde yeni bir konu oluşturmak, ancak mevcut havuzdan tekrar kullanmak. Havai yükü önemli ölçüde azaltır. Bir kod çözümüne girmeden, bir çeşit bariyer kullanmak istersiniz.
+0

Döngü değişkeni kapatmada kullanıldığı için bu yanlış çalışır. Yerel bir kopya oluşturmalısınız – VMAtm

+0

@ VMAtm Görev aynı döngü yinelemesi içinde bildirildiği, çalıştırıldığı ve bittiğinden, ben 'i' değiştirme olasılığı yok. Ben yanlış olabilir, tabii ki ... –

+1

Sadece f1 ve f2 çok havy ve syncronization yük olacaksa verimli olacaktır. – gabba

3

Bu algoritma sadece paralel kısım f1 ve f2 hesaplamadır Konu 2 Bu örnekteki iplik tek beklemek zorunda kalacak, ancak f1 söylemek ve f2 yüzden, zaman tüketim değil SIMD vektöreleştirme (örneğin C# içindeki System.Numerics.Vectors) kullanmak ve bir çekirdek üzerinde (önbellek kayıplarını da azaltır) çok daha iyi olabilir. Ya da muhtemelen algoritmanızı paralelleştirilebilecek şekilde değiştirebilirsiniz (ancak çok çalışmak gerekebilir).