【问题标题】:D taskpool wait untill all tasks are doneD taskpool 等到所有任务都完成
【发布时间】:2011-12-01 13:22:47
【问题描述】:

这与我之前的问题有关:D concurrent writing to buffer

假设您有一段由 2 个连续代码块 A 和 B 组成的代码,其中 B 依赖于 A。这在编程中很常见。 A 和 B 都包含一个循环,每个迭代都可以并行运行:

double[] array = [ ... ]; // has N elements

// A
for (int i = 0; i < N; i++)
{
    job1(array[i]); // new task
}

// wait for all job1's to be done

// B
for (int i = 0; i < N; i++)
{
    job2(array[i]); // new task
}

B 只能在 A 完成时执行。如何等到A的所有任务都完成后再执行B?

【问题讨论】:

    标签: concurrency parallel-processing task d wait


    【解决方案1】:

    我假设您使用的是 std.parallelism?我写了std.parallelism,所以我会让你做出设计决定。在 std.parallelism 的一些 beta 版本中实际上有一个 join 函数。它一直等到所有任务完成,然后关闭任务池。我删除了它,因为我意识到它没用。

    原因是,如果您手动创建一组 O(N) task 对象来迭代某个范围,那么您就是在滥用该库。您应该改用并行 foreach 循环,它会在将控制权释放回调用线程之前自动加入。您的示例将变为:

    foreach(ref elem; parallel(array)) {
        job1(elem); 
    }
    
    foreach(ref elem; parallel(array)) {
        job2(elem);
    }
    

    在这种情况下,job1job2 不应启动新任务,因为并行 foreach 循环已经使用了足够的任务来充分利用所有 CPU 内核。

    【讨论】:

    • 我明白你的意思。但是,如果我们想迭代使用 foreach 不那么直接的东西怎么办?如果你想遍历奇数索引怎么办?我需要构建一个新数组以便可以使用 foreach 吗?有 scopedTask 几乎可以满足我的需要,除了它的范围是迭代,而不是整个循环......
    • @Daevius:如果要遍历奇数索引,可以使用 std.range.stride 或 foreach(i; parallel(std.range.iota(1, array.length, 2)) . std.parallelism 的创建假设这种灵活性将由 std.algorithm 和 std.range 中的高阶范围提供,而不必在 std.parallelism 的设计中明确计划。
    • 是的,确实,由于范围创建的许多功能,这是一个简洁的设计。我的 2D FFT 算法在四核上的速度提高了约 200% :),谢谢。顺便说一句,iota 真的与希腊字母 Iota 有关吗? ^^
    • @Daevius 一点也不。该名称来自 C++ 的 iota 函数,因为它本质上做同样的事情。然而,这个名字实际上与它的实际作用没有任何关系。我不知道为什么选择它用于 C++。很多人不喜欢这个名字,因为真的没什么意思,但是和C++一致,好记。
    猜你喜欢
    • 1970-01-01
    • 2020-05-13
    • 2020-01-17
    • 1970-01-01
    • 2015-07-17
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多