我成功实现了这篇论文(仅用于我自己的研究)http://eprints.uwe.ac.uk/15260/,但是当遵循作者的特定实现时,我遇到了性能问题。使故事简单明了。我有一个Cell类,每个Cell存储在多维数组中,代表一个标量字段。 Cell类具有一种确定是否包含点的方法,这种遏制测试是导致我的代码出现严重性能问题的原因。
为澄清起见,在Cell类中,我有一个名为BoundingBox的方法(此处未显示),该方法计算一个正方形的4个顶点以确定容纳区域。这就是每个单元知道它是否包含粒子/代理的方式。在Contains方法中,m_domainX.Min…等用于保存包含区域的最小和最大坐标。我也只打电话给BoundingBox一次;我只是在类的构造函数中调用它。但是,Containment方法是在每个更新帧中计算的。
我通常使用150X150的阵列,大约4,000个粒子/试剂。基本上,数组越大,性能越低
我试图并行化该方法,但没有得到任何性能提升。
为说明起见,下面是一些模拟图像
// This method belons to the Cell<T> class, and will be used every update frame
public void Contains(List<PhysarumAgent> particles)
{
int ptsCount = 0;
foreach (var particle in particles)
{
if (particle.ForewordSensorB.X >= m_domainX.Min &&
particle.ForewordSensorB.X <= m_domainX.Max &&
particle.ForewordSensorB.Y >= m_domainY.Min &&
particle.ForewordSensorB.Y <= m_domainY.Max)
{
ptsCount++;
}
}
m_numAgentsInCell = ptsCount;
if (ptsCount > 1) m_occupied = true;
else m_occupied = false;
}
// This method belongs to another class. It iterates over the scalar field and calls
// the Contains() method for every cell in the field. Computed every update frame.
private static void ComputeField(SharpField2D<double> scalarField,
List<PhysarumAgent> PhysarumAgentPopulation)
{
ParallelOptions paraOpts = new ParallelOptions();
paraOpts.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
Parallel.For(0, scalarField.Columns, paraOpts, i =>
{
Parallel.For(0, scalarField.Rows, paraOpts, j =>
{
scalarField.Field[i, j].Contains(PhysarumAgentPopulation);
});
});
}
有任何指针将是很棒的,因为我不确定为什么这个简单的方法会引起很多问题。
答案 0 :(得分:0)
如果您的单元格形成规则的网格,则根本不需要运行任何测试。取而代之的是对粒子进行迭代,为每个粒子计算单元格索引,即将坐标除以单元格大小,然后调用Math.Floor,强制转换为int。如果您需要计算每个单元的点数计数器,或者以其他方式对每个单元聚集粒子,则以允许在每个单元中存储正在聚集的状态并逐步更新状态的方式编写该聚集代码。您可能需要遍历所有初始化的单元格,然后在处理所有粒子之后进行迭代,但这只需要按每个单元格而不是像当前比较那样按每个(单元格,粒子)对完成。