N-Body シミュレーションを書いています。計算を簡単にするために、空間全体を多数の均一なサイズの領域に分割しました。
各ボディについて、同じ領域内の他のすべてのボディの力を計算し、他の領域については、質量と距離を一緒に集計するので、実行する作業が少なくなります。
と があり、この反復で総質量を合計するものList<Region>
をRegion
定義します。public void Index()
Space.Tick()
関数には 2 つのバリアントがあります。
public void Tick()
{
foreach (Region r in Regions)
r.Index();
}
これは非常に速いです。20x20x20 = 8000 領域でそれぞれ 100 体 = 合計 800000 体の場合、これを行うのに約 0.1 秒しかかかりません。CPU グラフは、私のクアッドコアで 25% の使用率を示しています。これはまさに私が予想していたものです。
今、私はこのマルチスレッドバリアントを書きます:
public void Tick()
{
Thread[] threads = new Thread[Environment.ProcessorCount];
foreach (Region r in Regions)
while (true)
{
bool queued = false;
for (int i = 0; i < threads.Length; i++)
if (threads[i] == null || !threads[i].IsAlive)
{
Region s = r;
threads[i] = new Thread(s.Index);
threads[i].Start();
queued = true;
break;
}
if (queued)
break;
}
}
明らかでない場合の簡単な説明:threads
私の CPU の場合、4 の配列です。4x から始まりますnull
。領域ごとに、4 つThread
のオブジェクトすべて ( の可能性がありますnull
) をループします。null
いずれかまたはそうでないものを見つけたら、それとそれをIsAlive
キューに入れます。リージョンがインデックス作成を開始したことを確認できるように設定しました。Index()
Region
Start()
queued
true
このコードには約 7 秒かかります。それは70倍遅いです。スレッドの設定、空いているスレッドの検索などに多少のオーバーヘッドがあることは理解していますが、少なくとも何らかのパフォーマンスの向上は期待できます。
私は何を間違っていますか?