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)
您的第二个代码不正确。我认为正确的代码是这样的:
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)