线程缓慢且难以预测?

时间:2012-11-19 22:08:27

标签: c# .net multithreading

我已经创建了光线跟踪器的基础,这是我绘制场景的测试功能:

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。

3 个答案:

答案 0 :(得分:3)

如果不对您的应用进行分析,这很难回答,但我会怀疑错误分享。

两个线程都写入共享内存结构,这将导致CPU缓存无效。

测试的简便方法是为每个线程创建一个单独的输出数组。
它不必工作 - 只需查看帧速率。

我前段时间写了一篇关于此事的文章:“Concurrency Hazards: False Sharing

答案 1 :(得分:0)

线程通常不是渲染的方式。我不知道在线程中究竟执行了什么,但是创建线程并加入它们可能比并行计算所花费的时间更多。还取决于处理器内核的数量。

答案 2 :(得分:0)

实验:使用y交换x,在内部循环中使用x,在外部循环中使用y,并始终按行顺序分配每个线程的负载,而不是逐列(x)。

我的假设是基于以下事实:位图几乎总是与x方向上的内存地址一起存储。如果是这种情况,则CPU缓存上的当前内存访问模式很难,尤其是在使用多个线程时。