将.NET 4线程转换为.NET 2

Por*_*ing 5 .net c# multithreading unity-game-engine game-physics

我正在使用其他人的.NET 4开源平滑粒子流体动力学代码,我正在尝试将其转换为Unity项目,您只能依靠它来达到.NET 2标准.不幸的是,代码使用了Parallels类(这太棒了!)但是他使用了一个比较模糊的重载.任何人都可以在没有巨大性能影响的情况下看到在.NET 2中实现相同功能的好方法吗?

    Parallel.For(
        0,
        _numActiveParticles,
        () => new Vector2[MAX_PARTICLES],
        (i, state, accumulatedDelta) => calculateForce(_activeParticles[i], accumulatedDelta),
        (accumulatedDelta) =>
        {
            lock (_calculateForcesLock)
            {
                for (int i = _numActiveParticles - 1; i >= 0; i--)
                {
                    int index = _activeParticles[i];
                    _delta[index] += accumulatedDelta[index] / MULTIPLIER;
                }
            }
        }
    );
Run Code Online (Sandbox Code Playgroud)

认为这是代码所做的(非线程):

    for (int i = 0; i < _numActiveParticles; i++)
    {
        Vector2[] temp = new Vector2[MAX_PARTICLES];
        temp = calculateForce(_activeParticles[i], temp);


        for (int k = _numActiveParticles - 1; k >= 0; k--)
        {
            int index = _activeParticles[k];
            _delta[index] += temp[index] / MULTIPLIER;
        }
    }
Run Code Online (Sandbox Code Playgroud)

MRB*_*MRB 1

您的第二个代码不正确。我认为正确的代码是这样的:

var accumulatedDelta= new Vector2[MAX_PARTICLES];

for(int i = 0; i < _numActiveParticles; ++i)
{
    accumulatedDelta = calculateForce(_activeParticles[i], accumulatedDelta);
}

for (int i = _numActiveParticles - 1; i >= 0; i--)
{
    int index = _activeParticles[i];
    _delta[index] += accumulatedDelta[index] / MULTIPLIER;
}
Run Code Online (Sandbox Code Playgroud)

我不知道什么.net2有什么没有。不过你可以Parallel.For自己模拟一下。

对这种重载的解释Parallel.For是这样的:

第一个参数:循环的起始索引

第二个参数:循环结束索引

第三个参数:将创建任务本地数据的委托。对于每个Parallel.For使用(任务)的线程,将调用此委托并返回localInit数据。

第四个参数:充当 的主体的委托for。在第一次执行主体委托时,该委托将检索由前一个委托 ( ) 创建的数据localInit。在每个后续循环中,主体委托可以更改localInit,然后将其返回到下一个主体执行。在主体委托的最后一次执行中,localInit数据将传递给最后一个委托。

最后一个参数:当任务完成其工作时,每个任务将调用的另一个委托。localInit将传递给该代表。因为这个委托可以被多个任务调用并发,所以你必须保护你的共享数据。

编辑:

的一个版本ParallelFor可以是这样的:

public static void ParallerFor<TLocal>(int startIndex, int endIndex, Func<TLocal> initData, Func<int, TLocal, TLocal> body, Action<TLocal> finalizer)
    {
        int numThreads = Environment.ProcessorCount;
        int chunkOffset = ((endIndex - startIndex) / numThreads) + 1;

        Task[] tasks = new Task[numThreads];

        Enumerable.Range(0, numThreads).ToList().ForEach(x =>
            {
                int start = x * chunkOffset;
                int end = ((x + 1) * chunkOffset);
                end = end > endIndex ? endIndex : end;

                tasks[x] = Task.Factory.StartNew(() =>
                {
                    TLocal init = initData();

                    for(int i = start; i < end; ++i)
                    {
                        init = body(i, init);
                    }

                    finalizer(init);
                });
            });

        Task.WhenAll(tasks).Wait();
    }
Run Code Online (Sandbox Code Playgroud)