2011-06-21 1 views
4

私は、pthreadsを使用してCプログラムを作成して、二次元行列の波面パターン計算を行います。並列アプリケーションはランダムな振る舞いを持っています

スレッド0 ------------------

スレッド1:良好なパフォーマンスを実現するために、私はそうのように、インターリーブされた方法で、各スレッドに複数の行を配布します------------------

スレッド2 ------------------

スレッド3 - ----------------

スレッド0 ------------------

スレッド1 ---- ---------- ----

スレッド2 ------------------

スレッド3 ---------------- -

など

この計算で、私は、各スレッドが各行に計算された新しい値を必要とし、彼らが利用可能になるまでさらに移動することはできませんので、これは、唯一の実行可能な分割だと思います。 ここで、スレッド1はスレッド0によって計算された値をその行に必要とするので、スレッド0の後ろをたどり、先行しないでください。この目的のために、私は各行をチャンクに分割し、各チャンクをクリティカルセクションで保護しています。計算は次のようになります:

スレッド0 -----------

スレッド1 ------

スレッド2 ---

ように常にその行iは行i - 1の後ろを歩かなければなりません。 私はこの考え方を実装しており、デュアルクアッドコアシステムであるマシンでテストしています。私は奇妙な行動を経験しています。結果は正しく計算されますが、実行時間はシーケンシャル時間よりも8倍より小さく、シーケンシャル時間よりも長くなります。実際には、12000 x 12000マトリックスの連続時間は16秒で、パラレル実行時間は2〜17秒の間であり、2回の連続運転で異なる場合があります。

私の最初のアイデアは、この問題は非常に局所的であるため、もちろんスレッド0とスレッド1が別の物理プロセッサでスケジュールされているとしたら、パフォーマンスが悪くなる可能性があります。/proc/cpuinfoを見てみると、プロセッサ0に0,2,4,6があり、プロセッサ1に1,3,5,7があるようにコアがマッピングされていると推測しました。 スレッド作成時に、 pthread_setaffinity_npを使用して右コアのスレッドの親和性を設定しています。しかし、何も変わりません。私もpthread_attr_setaffinity_npとsched_setaffinityを使ってみましたが、同じランダム実行時間が得られます。

カーネルがアフィニティコールを無視しているか、これは問題ではありません。 アイデアが足りなくなったら誰かが私を助けてくれることを願っています。ありがとうございました。

+0

標準行列演算とベクトル演算に問題を減らし、既成の並列線形代数ライブラリを使用しています。 INTELかAMDからのオプションはありますか? –

+0

アプリケーションがほぼ完了しており、割り当てに基本スレッドを使用する必要があるので、恐れはありません。また、教訓的な理由からこの問題の原因を調べることは価値があると思います。 :) – Tudor

答えて

7

カーネルがアフィニティコールを無視しているわけではありません。問題ではありません。

キャッシュミスのようです。あなたのスレッドが同じデータで相互接続されていない場合は、これを避けるために行間に大きなギャップを作ることができます。

1行分のデータサイズのチャンクを作成してみてください。 スレッド0を64バイトにして、そのスレッド1が同じ場所から読み込むようにしてください。

+1

また、データが64バイト境界で整列されていることを確認する必要があります。 –

+0

先生、あなたは英雄です。このアライメントのアイデアは私の問題をエレガントに解決しました。 – Tudor

関連する問題