Parallel processing 需要帮助并行遍历D中的dag吗

Parallel processing 需要帮助并行遍历D中的dag吗,parallel-processing,d,graph-traversal,Parallel Processing,D,Graph Traversal,编辑:好的,这里有一个更简单的例子来说明我的问题。为什么只有第一个任务被放入队列 import std.stdio; import std.parallelism; void simpleWorker(uint depth, uint maxDepth, TaskPool pool){ writeln("Depth is: ",depth); if (++depth < maxDepth){ pool.put( task!simpleWorker(dept

编辑:好的,这里有一个更简单的例子来说明我的问题。为什么只有第一个任务被放入队列

import std.stdio;
import std.parallelism;

void simpleWorker(uint depth, uint maxDepth, TaskPool pool){
    writeln("Depth is: ",depth);
    if (++depth < maxDepth){
        pool.put( task!simpleWorker(depth,maxDepth,pool));
    }
}

void main(){
    auto pool = new TaskPool();
    pool.put(task!simpleWorker(0,5,pool));
    pool.finish(true);
    writeln("Done");
}

完整代码如下:

您有这样的行为,因为您的
canProcess()
除根节点以外的所有节点返回false。由于
cleanNodeSimple()
调用canProcess()检查是否将新任务放入池中,因此我相信它永远不会这样做。。。 检查此(已修改)程序的输出:

编辑: 此外,经过一些分析后,循环也只执行一次,因此不会向任务池添加任何内容。:)

代码已打开,请查看它。以下是可能帮助您解决问题的最有趣的部分:

// Dejan: will be called only once!
// Because canProcess() returns false for all children.
void cleanNodeSimple(Node node, TaskPool pool){
  node.doProcess();
  writeln("cleanNodeSimple() called for node `", node, "`"); 
  foreach (cli; node.clients){
    writeln("I am ", cli, " and I am executed only once, because I am only RootNode's client.");
    if (cli.canProcess()) {
      writeln("I will be executed only once because because ", cli, " has ", cli.clients.length, " clients.");
      writeln("And its master #1 is ", cli.clients[0].masters[0].dirty ? "dirty" : "clean");
      pool.put( task!cleanNodeSimple(cli, pool) );
    }
  }
}

这是因为simpleWorker中的put正在抛出一个错误

此版本显示错误:

import std.stdio;
import std.parallelism;

void simpleWorker(uint depth, uint maxDepth, TaskPool pool){
    writeln("Depth is: ",depth);
    if (++depth < maxDepth){
        try {
            pool.put( task!simpleWorker(depth,maxDepth,pool));
        } catch (Error e) {
            writeln("Fail: ", e.msg);
        }
    }
}

void main(){
    auto pool = new TaskPool();
    pool.put(task!simpleWorker(0,5,pool));
    pool.finish(true);
    writeln("Done");
}
希望其他人能够解释使用TaskPool的正确方法

编辑

通过告诉任务按如下方式运行,使其正常工作:

import std.stdio;
import std.parallelism;

void simpleWorker(uint depth, uint maxDepth, TaskPool pool){
    writeln("Depth is: ",depth);
    if (++depth < maxDepth){
        try 
        {
            auto subWorker = task!simpleWorker(depth,maxDepth, pool);
            pool.put(subWorker);
            subWorker.yieldForce();
        } catch (Error t) {
            writeln("Fail: (",  typeof(t).stringof, ") ", t.msg);
        }
    }
}

void main(){
    auto pool = new TaskPool();

    auto worker = task!simpleWorker(0,5, pool);
    pool.put(worker);
    worker.yieldForce();

    pool.finish(true);
    writeln("Done");
}

要以并行方式进行迭代,可以使用
parallel

foreach (client; pool.parallel(node.clients,1)){
    if (client.canProcess()){
        cleanNode(client, pool);//<- EDIT: no need to make a task here
    }
}
foreach(client;pool.parallel(node.clients,1)){
if(client.canProcess()){

cleanNode(client,pool);//这是一个可运行的代码版本:您可以使用fork,并在d-paste网站上轻松运行它……这是一个有用的工具,我可能会在以后的问题中使用它……但是您对如何使我的代码工作有什么见解吗?我希望每个节点都打印出“clean”。您所说的“clean”是什么意思?:)我的意思是这一行中的字符串“clean”:
writeln(d.dirty?,“\n”);
我首先将根节点放入队列中。然后在
doProcess()
中,根节点被清理,因此它的客户机应该返回
true
对于
canProcess()
否,请检查修改后的代码,您将(希望如此)理解。您所做的唯一一件事就是添加第61行,在
cleanNodeSimple()时将其打印出来
被调用。我知道它只被调用一次,但一旦在根节点上被调用,doProcess就会清理它,以便它应该允许将其客户端添加到队列中。为什么不呢?该死的编辑时间限制:-/所以我注释掉了
canProcess()
签入此版本后,新任务仍然没有进入队列。不是真的,我还对canProcess()进行了注释。-你为什么不知道canProcess()总是返回false?:)这是我编辑的重点,再加上将我的注释读到canProcess()上方法。我进一步修改了示例,这样您就可以看到它只经过一次循环。:)我认为工作版本会从代码中删除并行性。我非常确定,创建一个任务,然后强制它生成与调用函数在概念上是一样的。因此,我认为在这一点上它相当于单线程递归。我运行了使用不同的深度级别执行了几次,看起来您是对的。因此,我们仍然需要有人以正确的方式使用TaskPool来回答此问题。另一种方法是使用spawn()为了为simpleWorker.Hmm的每次运行创建一个新线程,我做了一次尝试,得到的只是一个疯狂的负shell返回,windows开始寻找一种方法来修复我的程序的问题。(不要真的相信这个输出,把它复制到你的机器上,然后运行它,看看我的意思)如果你并行执行,那么你可以替换
pool.put(任务!cleanNode(客户端,池));
cleanNode(客户端,池)
由于并行已经使其成为并行,这当然适用于较小的列表,但每个线程都会等待其所有节点的客户端递归完成。因此,如果我有深度为500的测试DAG,我将达到一个极限。在我当前的装备上,它达到380到410之间的极限。
import std.stdio;
import std.parallelism;

void simpleWorker(uint depth, uint maxDepth, TaskPool pool){
    writeln("Depth is: ",depth);
    if (++depth < maxDepth){
        try 
        {
            auto subWorker = task!simpleWorker(depth,maxDepth, pool);
            pool.put(subWorker);
            subWorker.yieldForce();
        } catch (Error t) {
            writeln("Fail: (",  typeof(t).stringof, ") ", t.msg);
        }
    }
}

void main(){
    auto pool = new TaskPool();

    auto worker = task!simpleWorker(0,5, pool);
    pool.put(worker);
    worker.yieldForce();

    pool.finish(true);
    writeln("Done");
}
Depth is: 0
Depth is: 1
Depth is: 2
Depth is: 3
Depth is: 4
Done
foreach (client; pool.parallel(node.clients,1)){
    if (client.canProcess()){
        cleanNode(client, pool);//<- EDIT: no need to make a task here
    }
}