2

私はずっと前に書いたコードを修正していましたが、スレッドをより有効に活用するために(そして一般的にプログラミングをより有効に活用するために)書き直すことにしました。

ここにあります:https ://github.com/buddhabrot/buddhabrot/blob/master/basic.c :

ブッダブロをフラクタルにするアプリケーションです。この質問の範囲外の理由により、これを最適化するためにメモ化を使用することは困難です。基本的に、これをプロファイルすると、99%以上の時間が最終的に行われる最も内側のループに費やされます。

buddhabrot[col][row]++;

複数のスレッドがこのコードを実行します。インクリメントはスレッドセーフではないため、メモリのこの部分で特定のミューテックスロックを使用しました。したがって、buddhabrotメモリ内のアドレス可能な各場所には個別のミューテックスがあります。

さて、これはもちろん1つのロックを使用するよりも効率的です(これにより、すべてのスレッドが互いに待機するようになります)が、メモリ効率は低くなります。ミューテックスもいくつかのデータを取得しているようです。また、何百万ものミューテックスを使用したpthreadの実装における他の影響についても疑問に思っていますか?

私は今、考慮すべき他の2つの戦略があります。

  • マップ内の「領域」ごとに、密度の低いミューテックスロックのセットを使用します。したがって、たとえば、[col / 16] [row / 16]のロックは、スレッドが別のスレッドと同じ16ピクセルの領域にアクセスした場合にのみスレッドをロックします。ロックの密度は動的に調整できます。しかし、これをモデル化しているときに、カーネルによって実装される可能性のある既存の問題を解決していないのではないかと思っていました。また、速度を落とさずにこれを作成する方法を見つけることもできません。「ミューテックスのツリー」についても考えましたが、このループ内ではすべてが遅すぎます(コンパイラの背後にあるいくつかの数学演算の順序を最適化した後、プロセッサ時間を約30%長くすることができました) 。このためのトピックはありますか、「ミューテックス密度計画」に関する詳細情報をどのように探すのですか?

  • 各スレッドのメモリをコピーして、その周りでミューテックスする必要がないようにします。しかし、これはさらにメモリ効率が悪くなります。それは、その影響を知らなくても、何百万ものミューテックスを持つという問題を解決します。

それで、他に何かありますか、私にもっと良いことがありますか?

4

3 に答える 3

4

Windows プラットフォームでは、intrin.h の InterlockedIncrement などのアトミック インクリメント関数を使用できます。

#include <intrin.h>

#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, _InterlockedExchange)
#define InterlockedExchangeAdd _InterlockedExchangeAdd
#define InterlockedIncrement _InterlockedIncrement
#define InterlockedDecrement _InterlockedDecrement
#define InterlockedCompareExchange _InterlockedCompareExchange
#define InterlockedExchange _InterlockedExchange

#pragma intrinsic(abs, fabs, labs, memcmp, memcpy, memset, strcat, strcmp, strcpy, strlen)
#pragma intrinsic(acos, cosh, pow, tanh, asin, fmod, sinh)
#pragma intrinsic(atan, exp, log10, sqrt, atan2, log, sin, tan, cos) 

この増分はアトミックであり、マトリックスに何百万ものミューテックスやグローバル ロックを設定する必要はありません。

于 2011-12-05T13:03:59.360 に答える
0

各スレッドが1列だけを更新するように、マトリックスを分割できるはずだと思います。そうすれば、彼らはお互いに邪魔をすることはなく、あなたはロックする必要はありません。

すべての列の中央同期キューを作成し、各スレッドをそこに移動させて列番号を取得すると、その列の値のみが更新され、すべてが完了するまで次の列のキューに移動します。

その場合、競合は中央のキューでのみ発生し、残りのキューと比較して取るに足らないものになるはずです。

また、各列に十分な行があると思います。そのため、誤った共有が発生したり、速度が低下したりすることはありません。

よろしくGJ

于 2011-12-05T13:14:32.553 に答える
0

2 番目のデザインは、まさにあなたが示した理由から、より良い選択です。ブッダブロットをレンダリングするには、合計の大きな行列を作成する必要があります。各プロセッサに独自の配列を計算させ、その結果を約 1 分ごとにマスター配列に追加すると、メモリの競合を回避できます。メモリ ロックが必要なのはその部分だけであり、各スレッドが独自のファイルに書き込むことで回避できます。複数のプロセッサがありますよね?そうでない場合、スレッドを追加してもメリットはありません。

于 2012-11-08T08:59:58.360 に答える