首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#资源竞争

C#资源竞争
EN

Stack Overflow用户
提问于 2014-06-09 03:10:44
回答 1查看 141关注 0票数 0

我正在为AI单元创建一个流场,并试图加快一些线程代码。我的测试网格大小为2000 x 2000,目前生成时间缩短到5.5秒。分析代码指出了一些似乎很奇怪的东西。我为线程使用的方法平均报告了140个包含在其中的争论。其中65个是这一行的。

代码语言:javascript
复制
var neighbours = GetNeighbors4(cell.Point);

下面是正在调用的方法。

代码语言:javascript
复制
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]
            };
        }

单元格只是一个简单的二维数组来表示网格。

代码语言:javascript
复制
IntegrationCell[,] Cells; 

现在它的工作方式是,给定网格中的目标细胞,我像一个“波”或“涟漪”从目标上走出来。每一次迭代波都会离目标更远一步。在我这样做的时候,每次迭代都有更多的单元格,因为距离目标的距离越大。对于每次迭代中的每个单元,我生成一个新线程,该线程计算单元格成本,并返回需要计算/重新计算的新单元格列表。会发生更多的事情,但基本上就是这样。在到达地图边缘之前,我曾经在大约120个线程上达到峰值,每次迭代时都会有较少的单元格,直到没有剩下的单元格。

这是每个单元格运行的线程的完整方法。(我一次可以跑超过100次)

代码语言:javascript
复制
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;
        }

我已就每一行所报告的争论发表意见。争论因每次运行而不同,但我无法理解的是,为什么我会从数组中进行争论?是的,我正在更新数组/单元及其邻居(如果需要的话),每个单元可能会被计算不止一次。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-11 23:40:57

对于每次迭代中的每个单元,我生成一个新线程.

也许这就是问题所在。由于您正在进行CPU绑定计算,因此只使用由静态属性指示的CPU拥有计算机的线程数:

代码语言:javascript
复制
System.Environment.ProcessorCount

否则,您会试图安排太多的时间,从而导致大量争用和上下文切换。

我的意思是,更多的线程并不意味着更快,实际上,它可能会因为线程管理开销而更慢地执行应用程序。当您有I/O绑定操作时,您使用更多的线程,因此许多线程处于空闲状态,等待其他地方发生的事情(例如: web服务调用、数据库操作、传入请求.)。

看看这个答案:https://stackoverflow.com/a/12021285/307976,还有关于如何用PLINQ限制并行性

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24113159

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档