我正在使用其他人的 .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;
}
}
}
);
我认为这就是代码的作用(非线程):
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;
}
}
最佳答案
您的第二个代码不正确。我认为正确的代码是这样的:
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;
}
我不知道 .net2
有什么,没有什么。但是您可以自己模拟 Parallel.For
。
Parallel.For
重载的解释是这样的:
第一个参数:循环起始索引
第二个参数:循环结束索引
第三个参数:将创建任务本地数据的委托(delegate)。对于 Parallel.For
使用的每个线程(任务),将调用此委托(delegate)并返回 localInit
数据。
第四个参数:作为for
主体的委托(delegate)。在 body delegate 的第一次执行中,该委托(delegate)将检索由 previuse delegate (localInit
) 创建的数据。在每个后续循环中,主体委托(delegate)可以更改 localInit
,然后将其返回给下一个主体执行。在主体委托(delegate)的最后一次执行中,localInit
数据将传递给最后一个委托(delegate)。
最后一个参数:每个任务将调用的另一个委托(delegate),当任务完成它的工作时。 localInit
将传递给此委托(delegate)。因为这个委托(delegate)可以被多个任务调用并发,所以你必须保护你的共享数据。
编辑:
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();
}
关于c# - 将 .NET 4 线程转换为 .NET 2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20652011/