2015-12-25 14 views
9

データが格納された配列x []があります。また、 "システム状態" c []の配列があります。プロセス: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つの並列スレッドを使用して2コアシステム上のf1f2の値を見つけるために、任意の効率的な方法はありますか?私は(擬似コードで)以下の意味:

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 
    } 
} 

f1f2は所望のスピードアップがX2についてです、時間消費ではなく、何回も計算する必要があります。グラフィカル表現するための図を参照してください:Windows用のコード例を探してい

desired parallel process

c[i-1]が利用可能

  • c[i]とき

  • +1

    F1、F2が非常にhavyている場合にのみefficienするwoulのsyncronizationのオーバーヘッドになるあまり、これはC#の**と** C++をタグ付けされているのはなぜ並列実行 – gabba

    +0

    の利益よりも?どの言語を使用していますか? –

    +0

    言語の選択は、タスクをより効率的に解決できるものによって異なります。 – carimus

    答えて

    4

    私は右のあなたを理解していればc[i-1]が利用可能

  • b[i]あるとき、

    • a[i]のみを計算することができのみを計算することができa[i]b[i]が計算されている場合にのみ使用可能です

    それは、別々に行うことができる唯一のプロセスは、a[i]b[i]と計算されていることを意味します。

    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; 
    } 
    

    これは、それぞれf1f2を計算します二つの別々のスレッドを実行します:私はC#でそれを見る方法です

    f1f2の両方が計算されると、c[i]という値が設定され、次の繰り返しが実行されます。

    • は、私はあなたには、いくつかの初期a[0]b[0]値を持っていると仮定して、あなたのf1f2リターンdouble
    • ループが1から始まると仮定して、doubleを使用しますことを

      注意。 f1f2の計算が本当にあればそうでない場合は、c[i-1]は(Threadを使用するとは違って)のThreadPoolを使用して他の計算

    • Task.Factory.StartNew
    • に比べて、リソースを消費し、長いそれはdoesnのことを意味している。これは、唯一の改善をもたらす例外
    • を投げるだろう毎回新しいスレッドを作成しますが、既存のプールをプールから再利用します。それは顕著にオーバーヘッドを減少させる。
  • +0

    ループ変数がクロージャーで使用されるため、これは正しく機能しません。 – VMAtm

    +0

    @VMAtmタスクは宣言されて実行され、同じループ反復で終了するので、私は 'i'の変更の可能性は見当たりません。私はF1、F2は意志少ない。もちろん、並列実行 –

    +1

    ...もちろん、間違っている可能性があります!明確化のためにありがとうございます。私は答えを更新して、OPがあなたのアドバイスに従うことを願っています。 – gabba

    2

    コードソリューションに入ることなく、何らかのバリアを使用したいと考えています。これにより、すべての参加者がタスクを完了したことを宣言したかどうかを確認することができます。スレッド2はそう、このアルゴリズムでは唯一の平行部はf1とf2の計算ですが、F1、F2は、時間消費されないことを言う

    https://en.wikipedia.org/wiki/Barrier_(computer_science) Example of C++ "Memory barrier"

    3

    この例では、スレッド1のために待機する必要がありますSIMDベクトル化(C#のSystem.Numerics.Vectorsなど)を使用して、それを1つのコアで実行すること(キャッシュミスを減らすこと)がはるかに良いかもしれません。あるいは、あなたのアルゴリズムを並列化できるように変更することもできます(ただし、苦労するかもしれません)。