5

レイ トレーサーの基礎を作成しました。シーンを描画するためのテスト関数を次に示します。

public void Trace(int start, int jump, Sphere testSphere)
{
    for (int x = start; x < scene.SceneWidth; x += jump)
    {
        for (int y = 0; y < scene.SceneHeight; y++)
        {
            Ray fired = Ray.FireThroughPixel(scene, x, y);

            if (testSphere.Intersects(fired))
                sceneRenderer.SetPixel(x, y, Color.Red);
            else sceneRenderer.SetPixel(x, y, Color.Black);
        }
    }
}

SetPixel は、色の 1 次元配列に値を設定するだけです。関数を直接呼び出すだけで通常どおり呼び出すと、一定の 55 fps で実行されます。私が行った場合:

Thread t1 = new Thread(() => Trace(0, 1, testSphere));
t1.Start();
t1.Join();

それは一定の50fpsで実行されますが、これは問題なく理解できますが、実行すると:

Thread t1 = new Thread(() => Trace(0, 2, testSphere));
Thread t2 = new Thread(() => Trace(1, 2, testSphere));

t1.Start();
t2.Start();

t1.Join();
t2.Join();

それはあらゆる場所で実行され、30 ~ 40 fps の間で急速に移動し、時にはその範囲から 50 まで、または 20 まで下がります。まったく一定ではありません。すべてを単一のスレッドで実行した場合よりも実行速度が遅いのはなぜですか? クアッドコア i5 2500k で実行しています。

4

3 に答える 3

3

アプリのプロファイリングをせずにこれに答えるのは難しいですが、偽の共有が疑われます。

両方のスレッドが共有メモリ構造に書き込みを行っているため、CPU キャッシュが無効になり続けます。

テストする簡単な方法は、スレッドごとに個別の出力配列を作成することです。
動作する必要はありません。フレーム レートを確認してください。

しばらく前に、これについての記事を書きました:「同時実行の危険性: 偽の共有

于 2012-11-19T22:26:24.333 に答える
0

通常、スレッド化はレンダリングに適した方法ではありません。スレッド内で正確に何が実行されているかはわかりませんが、並列計算で得られるよりも、スレッドを作成して結合する方が時間がかかる可能性があります。プロセッサコアの量にも依存します。

于 2012-11-19T22:19:15.197 に答える
0

実験: x を y と交換し、内側のループで x を通過し、外側のループで y を通過し、スレッドごとに常に行方向に負荷を分散し、列方向には分散しません (x)。

私の仮定は、ほとんどの場合、ビットマップは x 方向の昇順のメモリ アドレスで格納されるという事実に基づいています。その場合、特に複数のスレッドが使用されている場合、現在のメモリ アクセス パターンは CPU キャッシュでハードです。

于 2012-11-19T22:56:03.337 に答える