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 只是在颜色的一维数组中设置一个值。如果我通过直接调用它来正常调用该函数,它会以恒定的 55fps 运行。如果我做:

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-direction 的升序内存地址存储。如果是这种情况,则您当前的内存访问模式在 CPU 缓存上很困难,尤其是在使用多个线程时。

于 2012-11-19T22:56:03.337 回答