2

나는 그것을 위해 나는이 클래스를 사용하고, 트리 구조를 가지고있다. 그래서 노드의 경로를 설정하려면 부모 경로가 필요합니다.재귀 적 방법으로 병렬 처리를 구현하는 방법은 무엇입니까?</p> <pre><code>class Node { long IdNode; List<Node> Childs; string path; Data data; } </code></pre> <p>경로에 의해 단락 지어진 IdNode, 그래서 노드의 경로 등등 "IdParent.IdNode"이고 "."

public setPath(Node paramParentNode) 
{ 
    this.path = paramParentNode.Path + "." + this.IDNode; 

    foreach(Node iteratorNode in this.Childs) 
    { 
     iteratorNode.setPath(this); 
    } 
} 

이것은 secuential 버전 :

나는이 방법을 가지고있다. 하지만, 병렬로 그런 일이 구현하는 방법을 생각했다 :

public setPathMt(Node paramParentNode) 
{ 
    this.path = paramParentNode.Path + "." + this.IDNode; 

    Parallel.Foreach(this.Childs, 
    (iteratorNode) => 
     { 
      iteratorNode.SetPathMt(this); 
     } 
    ); 
} 

을하지만 모르는이 올바른 방법으로, 나는이 방법의 재귀 호출을 기다리는 방법을 알고하지 않기 때문에, 재귀 적 방법이 언제 끝났는지 어떻게 알 수 있습니까?

다중 스레드 재귀 적 방법을 구현하는 가장 좋은 방법은 무엇입니까?

감사합니다. 당신은 모든 방법에서 전달 된 노드를 사용하지 않는 한이

public SetPathMt(Node paramParentNode) 
{ 
    paramParentNode.Path = paramParentNode.Path + "." + this.IDNode; 

    Parallel.Foreach(paramParentNode.Childs, 
    new ParallelOptions { MaxDegreeOfParallelism = 32 }, 
    (iteratorNode) => 
     { 
      SetPathMt(iteratorNode); 
     } 
    ); 
} 

같은

public SetPath(Node paramParentNode) 
{ 
    paramParentNode.Path = paramParentNode.Path + "." + this.IDNode; 

    foreach(Node iteratorNode in paramParentNode.Childs) 
    { 
     SetPath(iteratorNode); 
    } 
} 

및 병렬 방식처럼

+3

왜 그런 것들을 병렬 처리합니까? 연속 된 버전에서 2 개의 문자열을 점으로 연결하면 시간이 많이 걸리지 않을까요? – Evk

답변

1

귀하의 방법이 있어야한다. this을 사용하면 해당 클래스의 인스턴스를 의미하며 모든 재귀 메서드에서 동일하게 유지됩니다. 변경되는 유일한 방법은 메서드에서 전달되는 매개 변수입니다.

new ParallelOptions { MaxDegreeOfParallelism = 32 }은이 병렬 작업에서 사용하는 동시 작업 (스레드)의 수를 32 개 (원하는 숫자 일 수 있음) 또는 -1 (사용 가능한 모든 스레드 수)으로 제한합니다.

+1

여기서 병렬 처리가 어디에 있습니까? – Evk

+0

@Evk : 그게 다가오고있었습니다. –

+0

'새로운 ParallelOptions {MaxDegreeOfParallelism = 32} '(또는 합리적인 것)을 추가 할 수 있습니다. 그러나 실제로이 제한이 Parallel.ForEach에 대한 동시 호출, 또는 각 호출에 적용되는지 여부는 확실하지 않습니다. 즉, 트리가 1000 레벨 이상이라면 한 번에 많은 스레드를 실행할 수 있습니다. –

0

왜이 작업을 병렬로 실행해야하는지 잘 모르겠습니다. 어떤 이점을 얻으려면 커다란 나무가 필요하다고 생각합니다. 그러나 두 방법은 다음 코드는 경로를 구축 완전한 작동 예입니다 당신이 그들을 spec'd과 같이

using NUnit.Framework; 
using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
using System.Threading.Tasks; 

namespace ClassLibrary2 { 

    [TestFixture] 
    public class NodePathHandler { 

     [Test] 
     public void SetNodePathsTest() { 
      var tree = new Node() { 
       IdNode = 1, 
       Childs = Enumerable.Range(1, 2).Select(nId1 => new Node() { 
        IdNode = 1 + nId1, 
        Childs = Enumerable.Range(1, 2).Select(nId2 => new Node() { 
         IdNode = nId1 + nId2, 
         Childs = Enumerable.Range(1, 2).Select(nId3 => new Node() { 
          IdNode = nId2 + nId3, 
          Childs = Enumerable.Empty<Node>().ToList() 
         }).ToList() 
        }).ToList() 
       }).ToList() 
      }; 
      var sw = Stopwatch.StartNew(); 
      SetNodePaths(tree); 
      Console.WriteLine($"Time: {sw.ElapsedMilliseconds}ms"); 
     } 

     public void SetNodePaths(Node node, string parentPath = null) { 
      node.Path = parentPath == null ? node.IdNode.ToString() : $"{parentPath}.{node.IdNode}";    
      //Sequential 
      //node.Childs.ForEach(n => SetNodePaths(n, node.Path)); 
      //Parallel 
      Parallel.ForEach(node.Childs, n => SetNodePaths(n, node.Path)); 
      Console.WriteLine($"Node Id: {node.IdNode} Node Path: {node.Path}"); 
     } 
    } 

    public class Node { 
     public long IdNode { get; set; } 
     public List<Node> Childs { get; set; } 
     public string Path { get; set; } 
     public Data Data { get; set; } 
    } 

    public class Data { } 
} 

그리고 작은 샘플 트리의 출력은 다음과 같습니다

Node Id: 2 Node Path: 1.2.2.2 
Node Id: 3 Node Path: 1.2.2.3 
Node Id: 2 Node Path: 1.2.2 
Node Id: 3 Node Path: 1.2.3.3 
Node Id: 2 Node Path: 1.3.3.2 
Node Id: 3 Node Path: 1.3.4.3 
Node Id: 3 Node Path: 1.3.3.3 
Node Id: 3 Node Path: 1.3.3 
Node Id: 4 Node Path: 1.2.3.4 
Node Id: 4 Node Path: 1.3.4.4 
Node Id: 4 Node Path: 1.3.4 
Node Id: 3 Node Path: 1.2.3 
Node Id: 3 Node Path: 1.3 
Node Id: 2 Node Path: 1.2 
Node Id: 1 Node Path: 1 
Time: 4ms 

주목해야 할 또 다른 옵션 Sequential 예를 가지고 대신 AsParallel().ForAll에 전화를 걸면됩니다. 보통은 Parallel 클래스보다 더 많은 오버 헤드를 나타냅니다. 그러나 성능에 대해 정말로 염려한다면 변형이 혼합에 유용합니다.

관련 문제