并行的本地变量foreach循环c#

时间:2017-08-06 13:52:26

标签: c# foreach parallel-processing

我有两个嵌套的foreach循环,需要运行大量的数据和计算。常规foreach循环耗时太长(几个小时)。

所以,我找到了加快速度的方法并找到Parallel.ForEach。这是我第一次处理并行化,但examples似乎很容易。

以下是我的代码,这个问题是局部变量(我认为,至少)。为在并行循环之外工作正常的节点添加错误。

Parallel.ForEach(allNodes, (startNode) =>
{
    Parallel.ForEach(allNodes, (endNode) =>
    {
        if (startNode != endNode)
        {
            List<Geo_Model_Struct> route = pathfinder.getRouteOptimised(startNode, endNode);

            if (route.Count <= 0)
            {
                //failed to find route
                errors.Add(string.Format("Cound not find a route from {0} to {1}", startNode, endNode));
            }
            else
            {
                List<Geo_Model_Struct> accessibleRoute = accessiblePathfinder.getRouteOptimised(startNode, endNode);
                if (accessibleRoute.Count <= 0)
                {
                    //failed to find route
                    errors.Add(string.Format("Cound not find an accessible route from {0} to {1}", startNode, endNode));
                }
            }            
        }
        endCount++;
        System.Diagnostics.Debug.WriteLine("I: {0}/{1}\tJ: {2}/{3}", startCount, allNodes.Count - 1, endCount, allNodes.Count - 1);
    }
  );
    startCount++;
});

我猜测它与route局部变量有关,因为几乎所有已检查的路线都失败了。但是我不知道如何可靠地调试这种东西,所以任何帮助都会受到赞赏。

修改

我正在测试所有可能的路线,以确保它们都能正常工作。对于大多数测试,route.Count应为> 0。使用传统的foreach循环时就是这种情况(例如500次中的15次route.Count <= 0true

在大多数情况下使用Parallel.ForEach route.Count 0时(例如,在500次中的494区域内),实际上很少有人通过测试并且在查看时大多数错误并行失败,使用传统的foreach

传递

解决

我找到了一种方法来消除在getRouteOptimised方法中从数据库中获取数据的需要。这解决了这个问题。仍然不确定导致问题的db连接到底是什么,但现在可以正常工作。

1 个答案:

答案 0 :(得分:1)

在没有看到其余代码的情况下,我怀疑问题在于pathfinder和accessiblepathfinder对象。它们可能不是线程安全的。 可能绕过这种方法的方法是在内部foreach循环中本地创建这些变量。

if (startNode != endNode)
{
    // Create and Initialise pathfinder here
    MyPathFinderObject pathfinder = new MyPathFinderObject(<parameters>);
    List<Geo_Model_Struct> route = pathfinder.getRouteOptimised(startNode, endNode);

    if (route.Count <= 0)
        .../...
    else
    {                        
        // Create and Initialise accessiblePathfinder here
        MyAccessiblePathFinderObject accessiblePathfinder = new MyAccessiblePathFinderObject(<parameters>);
        List<Geo_Model_Struct> accessibleRoute = accessiblePathfinder.getRouteOptimised(startNode, endNode);
        .../...
    }            
}

然而,无法保证这会奏效。

From the docs

  

从属性和方法获取数据时,您必须非常谨慎。众所周知,大型物体模型以令人难以置信的迂回方式共享可变状态。