并行用于不使用锁的共享数组

时间:2017-03-14 17:04:23

标签: c# multithreading concurrency task-parallel-library

Parallel.For循环中修改值类型数组内容的最佳方法是什么,其中每个任务都可能修改同一索引的数据。

在下面的代码中,sum_normals数组并不总是包含正确的求和值。

我可以使用锁,但我发现同步运行会更快。创建一个值为并发包的字典,并使用aggregation / sum计算另一个循环中的总和。

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;
});

1 个答案:

答案 0 :(得分:1)

Parallel.For has an overload允许在线程开始和线程结束时运行的函数(body函数的1次以上迭代可以在线程的生命周期内执行)。在这些功能中,您可以创建要写入的本地存储,然后在清理阶段将该本地存储添加到组存储。

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];
            }
        }
    });

请注意,根据...中的工作量,它可能会更快,只是不要并行执行此操作。