2017-08-06 12 views
1

我有兩個嵌套的foreach循環,需要運行大量的數據和計算。經常foreach循環花了太久(幾個小時)。並行foreach循環的局部變量c#

所以,我查了一下加速的方法,發現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循環是這樣的話(例如15出的500倍route.Count <= 0true

當使用Parallel.ForEachroute.Count0大部分時間(例如在494出500倍的區域的某個地方),所以很少實際上通過測試來看,在錯誤的時候產生的,在平行失敗的最多,通過採用傳統foreach

解決

我找到了一種方法來刪除需要獲取數據FR om在getRouteOptimised方法中的數據庫。這解決了這個問題。仍然不確定究竟是什麼導致問題的數據庫連接,但它現在起作用。

+0

我認爲我們需要看到'pathfinder.getRouteOptimised'和'accessiblePathfinder.getRouteOptimised'的代碼可能存在干擾調用這些方法的併發性。 –

+0

你的問題很可能是你保持的數量。這是一個鎖定的int嗎?如果不是,它需要爲了工作,儘管在並行循環中保持計數在大多數情況下並不是最好的想法。伯爵的目標是什麼?你的錯誤集合也是一個線程安全集合? –

回答

1

沒有看到你的代碼的其餘部分,我懷疑這個問題是與探路者和accessiblepathfinder對象。它們可能不是線程安全的。 A 可能避免這種情況的方法是在內部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

正從屬性和方法的數據時,你必須非常謹慎。大型對象模型以令人難以置信的方式共享可變狀態而聞名。