Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Threading is slow and unpredictable?

I've created the basis of a ray tracer, here's my testing function for drawing the scene:

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 simply sets a value in a single dimensional array of colours. If I call the function normally by just directly calling it it runs at a constant 55fps. If I do:

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

It runs at a constant 50fps which is fine and understandable, but when I do:

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

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

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

It runs all over the place, rapidly moving between 30-40 fps and sometimes going out of that range up to 50 or down to 20, it's not constant at all. Why is it running slower than it would if I ran the whole thing on a single thread? I'm running on a quad core i5 2500k.

like image 338
Levi H Avatar asked Oct 22 '22 01:10

Levi H


1 Answers

This is difficult to answer without profiling your app, but I would suspect false sharing.

Both your threads are writing to a shared memory structure, which will cause your CPU caches to keep invalidating.

The easy way to test would be to create a separate output array for each thread.
It doesn't have to work - just look at the frame rates.

I wrote an article about this a while back: "Concurrency Hazards: False Sharing"

like image 197
Nick Butler Avatar answered Oct 24 '22 18:10

Nick Butler