zman
zman

Reputation: 353

Parallel For over shared array without using lock

What is the best approach for modifying the content of an array of value types in a Parallel.For loop, where each task may potentially modify the data for the same index.

In the code below the sum_normals array will not always contain the correct summation values.

I could use a lock but I found it would be faster to just run synchronously. Create a dictionary with a value a concurrent bag and use aggregation/sum to calculate the sum in another loop.

var sum_normals = new Vector3[Count];

Parallel.For(0, list.Count, options, i =>
{
    var index_1 = ...
    var index_2 = ...
    var index_3 = ...
    Vector3 normal = ...

    sum_normals[index_1] += normal;
    sum_normals[index_2] += normal;
    sum_normals[index_3] += normal;
});

Upvotes: 2

Views: 739

Answers (1)

Scott Chamberlain
Scott Chamberlain

Reputation: 127603

Parallel.For has an overload that allows for functions that run at thread start and thread end (more than 1 iteration of the body function may execute over the lifetime of the thread). In these functions, you can create a local storage to write to then add that local storage to the group storage in the cleanup phase.

var sum_normals = new Vector3[Count];

Parallel.For(0, list.Count, options, 
    () =>  //localInit
    {
        return new Vector3[sum_normals.Length];
    },
    (i, loopState, localArray) => //body
    {
        var index_1 = ...
        var index_2 = ...
        var index_3 = ...
        var normal = ...

        localArray[index_1] += normal;
        localArray[index_2] += normal;
        localArray[index_3] += normal;

        return localArray;
    },
    localArray => //localFinally
    {
        lock(sum_normals)
        {
            for(int i = 0; i < sum_normals.Length; i++)
            {
                sum_normals[i] += localArray[i];
            }
        }
    });

Note depending on the amount of work being done in the ... it still might be faster just not to do this in parallel.

Upvotes: 2

Related Questions