我正在为AI单元创建一个流场,并试图加快一些线程代码。我的测试网格大小为2000 x 2000,目前生成时间缩短到5.5秒。分析代码指出了一些似乎很奇怪的东西。我为线程使用的方法平均报告了140个包含在其中的争论。其中65个是这一行的。
var neighbours = GetNeighbors4(cell.Point);下面是正在调用的方法。
private IEnumerable<IntegrationCell> GetNeighbors4(Point point)
{
var sizeX = _size.X - 1;
var sizeY = _size.Y - 1;
var x = point.X;
var y = point.Y;
//corners
if (x == 0 && y == 0)
{
return new[]
{
Cells[1, 0],
Cells[0, 1]
};
}
if (x == sizeX && y == 0)
{
return new[]
{
Cells[sizeX - 1, 0],
Cells[sizeX, 1]
};
}
if (x == 0 && y == sizeY)
{
return new[]
{
Cells[0, sizeY - 1],
Cells[1, sizeY]
};
}
if (x == sizeX && y == sizeY)
{
return new[]
{
Cells[sizeX - 1, sizeY],
Cells[sizeX, sizeY - 1]
};
}
//top row
if (y == 0)
{
return new[]
{
Cells[x - 1, 0],
Cells[x + 1, 0],
Cells[x, 1]
};
}
//bottom row
if (y == sizeY)
{
return new[]
{
Cells[x - 1, y],
Cells[x + 1, y],
Cells[x, y - 1]
};
}
//left column
if (x == 0)
{
return new[]
{
Cells[0, y - 1],
Cells[0, y + 1],
Cells[1, y]
};
}
//right column
if (x == sizeX)
{
return new[]
{
Cells[x, y - 1],
Cells[x, y + 1],
Cells[x - 1, y]
};
}
//everything else
return new[]
{
Cells[x, y - 1],
Cells[x, y + 1],
Cells[x - 1, y],
Cells[x + 1, y]
};
}单元格只是一个简单的二维数组来表示网格。
IntegrationCell[,] Cells; 现在它的工作方式是,给定网格中的目标细胞,我像一个“波”或“涟漪”从目标上走出来。每一次迭代波都会离目标更远一步。在我这样做的时候,每次迭代都有更多的单元格,因为距离目标的距离越大。对于每次迭代中的每个单元,我生成一个新线程,该线程计算单元格成本,并返回需要计算/重新计算的新单元格列表。会发生更多的事情,但基本上就是这样。在到达地图边缘之前,我曾经在大约120个线程上达到峰值,每次迭代时都会有较少的单元格,直到没有剩下的单元格。
这是每个单元格运行的线程的完整方法。(我一次可以跑超过100次)
private IEnumerable<IntegrationCell> CostStep(IntegrationCell cell)
{
var result = new List<IntegrationCell>(); \\14 contentions
var costBlock = _costfield.Cells[cell.Point.X, cell.Point.Y];
if (costBlock.Cost == 255)
return result;
var neighbours = GetNeighbors4(cell.Point); \\65 contentions
foreach (var neighbour in neighbours) \\18 contentions
{
var newCost = costBlock.Cost + neighbour.Cost;
if (cell.Cost > newCost)
cell.Cost = newCost;
var childCostBlock = _costfield.Cells[neighbour.Point.X, neighbour.Point.Y];
var newChildCost = cell.Cost + childCostBlock.Cost;
if (childCostBlock.Cost == 255)
neighbour.Cost = 255;
else if (neighbour.Cost > newChildCost)
{
neighbour.Cost = newChildCost;
result.Add(neighbour); \\39 contentions
}
}
return result;
}我已就每一行所报告的争论发表意见。争论因每次运行而不同,但我无法理解的是,为什么我会从数组中进行争论?是的,我正在更新数组/单元及其邻居(如果需要的话),每个单元可能会被计算不止一次。
发布于 2014-06-11 23:40:57
对于每次迭代中的每个单元,我生成一个新线程.
也许这就是问题所在。由于您正在进行CPU绑定计算,因此只使用由静态属性指示的CPU拥有计算机的线程数:
System.Environment.ProcessorCount否则,您会试图安排太多的时间,从而导致大量争用和上下文切换。
我的意思是,更多的线程并不意味着更快,实际上,它可能会因为线程管理开销而更慢地执行应用程序。当您有I/O绑定操作时,您使用更多的线程,因此许多线程处于空闲状态,等待其他地方发生的事情(例如: web服务调用、数据库操作、传入请求.)。
看看这个答案:https://stackoverflow.com/a/12021285/307976,还有关于如何用PLINQ限制并行性。
https://stackoverflow.com/questions/24113159
复制相似问题