小编Jas*_*dez的帖子

C#中的并行树遍历

我需要快速遍历一棵树,我想并行完成.我宁愿使用并行扩展而不是手动旋转一堆线程.

我当前的代码看起来像这样:

   public void Traverse(Node root)
    {
        var nodeQueue = new Queue<Node>();
        nodeQueue.Enqueue(root);
        while (nodeQueue.Count!=0)
        {
            var node = nodeQueue.Dequeue();
            if (node.Property = someValue) DoSomething(node);
            foreach (var node in node.Children)
            {
                nodeQueue.Enqueue(node);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我真的希望Parallel.ForEach有一个Parallel.While模拟.我遇到了Stephen Toub关于使用Parallel.ForEach实现Parallels Parallel的文章.如果正确读取它仍然无法工作,因为我正在改变我试图迭代的队列.

我是否需要使用任务工厂和递归(这有风险吗?)?还是有一些我忽略的简单解决方案?

编辑:@svick

该树有超过250,000个节点.现在最大深度是14个节点,包括根.

根目录下有大约500个节点,之后的平衡具有相当随机的分布.我很快就会得到更好的分布统计数据.

@Enigmativity:

是的,许多用户同时修改了树,但我通常会为树或子树提供共​​享读锁,或允许脏读.

对node.Children的调用可以被认为是原子的.

DoSomething实际上是几个代理之一,对于一些昂贵的操作,我可能会收集节点的快照列表并在遍历之外处理它们.

我意识到我应该看一般情况(遍历的子树而不是整个树.)为此,我在树的每个节点上运行遍历并查看总时间.

我为每个遍历算法使用了Parallel.ForEach(nodes,Traverse),其中节点包含所有~250k节点.这模拟(某种程度上)许多用户同时请求许多不同的节点.

00256ms广度优先顺序

00323ms广度优先连续工作(我将静态计数器增加为"工作")

01495ms Kirks第一个回答

01143ms Svicks第二个答案

00000ms Recursive Single Threaded在60s后没有完成

00000ms电子书的答案在60年代后没有完成

@Enigma,我想我可能会以某种方式搞砸你的算法,因为它似乎应该更快.

结果令我惊讶的是至少可以说.为了让自己相信编译器并没有神奇地优化遍历,我不得不在广度第一顺序中添加一些工作.

对于头部的单次遍历,并行化第一级仅具有最佳性能.但几乎没有,这个数字有所改善,因为我向第二级添加了更多节点(2000而不是500).

c# parallel-processing tree-traversal task-parallel-library

13
推荐指数
1
解决办法
5143
查看次数

是否可以确定IEnumerable <T>是否已将执行挂起?

我有一个接受Enumerable的函数.我需要确保对枚举数进行评估,但是如果它在List或其他"冻结"集合中已经准备就绪,我宁愿不创建它的副本(例如,通过ToList()或ToArray()).冻结我指的是已经建立了一组项目的集合,例如List,Array,FsharpSet,Collection等,而不是像Select()和where()这样的linq.

是否有可能创建一个函数"ForceEvaluation",可以确定枚举是否已将执行挂起,然后评估可枚举?

 public void Process(IEnumerable<Foo> foos)
 {
      IEnumerable<Foo> evalutedFoos = ForceEvaluation(foos)
      EnterLockedMode(); // all the deferred processing needs to have been done before this line. 
      foreach (Foo foo in foos) 
      {
           Bar(foo);
      }  
}

 public IEnumerable ForceEvaluation(IEnumerable<Foo> foos)
 {
      if(??????)
      { return foos}
      else
      {return foos.ToList()}

 }
Run Code Online (Sandbox Code Playgroud)

}

经过一些研究后,我意识到这在任何实际意义上都是不可能的,并且需要对每个迭代器进行复杂的代码检查.

所以我将使用Mark的答案的变体并创建一个已知安全类型的白名单,并且只需调用ToList()不在白名单上的任何内容.

感谢大家的帮助.

编辑*经过更多的反思,我意识到这相当于停止问题.所以非常不可能.

c# linq deferred-execution

10
推荐指数
2
解决办法
804
查看次数

有一个好的整数只有行光栅化算法吗?

我一直在努力构建一个简单的3D图形引擎,我正在尝试找到一个好的基于整数的线光栅化算法.(我不是想重新发明轮子,我试图更深入地了解轮子).

是否有任何线光栅化算法不依赖于任何浮点数学?

谢谢.

algorithm graphics rasterizing

4
推荐指数
1
解决办法
620
查看次数

是否有一个C#datetime库可以处理从现在到公元前12,000年的日期?

这就是它.我不需要旧石器时代的高精度,但我希望能够代表这些日期而不会跳过太多的箍.

c# datetime

3
推荐指数
1
解决办法
1421
查看次数