【问题标题】:How do i write tasks? (parallel code)任务怎么写? (平行码)
【发布时间】:2010-05-11 22:19:57
【问题描述】:

英特尔线程构建块给我留下了深刻的印象。我喜欢我应该如何编写任务而不是线程代码,并且我喜欢它在我有限的理解下如何工作(任务在一个池中,4核上不会有100个线程,一个任务不能保证运行,因为它不在它自己的线程,可能在池中很远。但它可能与另一个相关任务一起运行,所以你不能做像典型的线程不安全代码这样的坏事。

我想了解更多关于写作任务的信息。我喜欢这里的“基于任务的多线程 - 如何为 100 个内核编程”视频http://www.gdcvault.com/sponsor.php?sponsor_id=1(目前是倒数第二个链接。警告它不是“很棒”)。我最喜欢的部分是“最好并行解决迷宫”,大约在 48 分钟左右(您可以点击左侧的链接。如果有的话,这部分真的是您需要观看的全部内容)。

但是我喜欢看更多的代码示例和一些关于如何编写任务的 API。谁有好的资源?我不知道一个类或一段代码在将其推送到池后会是什么样子,或者当您需要复制所有内容以及将所有内容推送到池中时,代码会是什么样子。

【问题讨论】:

    标签: parallel-processing tbb


    【解决方案1】:

    Java 有一个类似于 Thread Building Blocks 的并行任务框架——它被称为 Fork-Join 框架。它是available,用于当前的 Java SE 6 并包含在即将推出的 Java SE 7 中。

    除了 javadoc 类文档之外,还有一些资源可用于开始使用该框架。来自jsr166 page,提到 “还有一个 wiki,其中包含这些课程的其他文档、注释、建议、示例等。”

    fork-join examples,比如矩阵乘法是一个很好的起点。

    我在解决一些Intel's 2009 threading challenges 时使用了fork-join 框架。该框架是轻量级和低开销的——我的是骑士巡回赛问题的唯一 Java 条目,它在比赛中的表现优于其他条目。 Java 源代码和文章可从挑战网站下载。

    编辑:

    我不知道一个类或部分如何 的代码可能会在将其推送到 一个游泳池 [...]

    您可以通过继承ForKJoinTask 子类之一来创建自己的任务,例如RecursiveTask。这是并行计算斐波那契数列的方法。 (取自RecursiveTask javadocs - cmets 是我的。)

     // declare a new task, that itself spawns subtasks. 
     // The task returns an Integer result.
     class Fibonacci extends RecursiveTask<Integer> {
       final int n;      // the n'th number in the fibonacci sequence to compute
       Fibonnaci(int n) { this.n = n; } // constructor
       Integer compute() {   // this method is the main work of the task
         if (n <= 1)         // 1 or 0, base case to end recursion
            return n;
         Fibonacci f1 = new Fibonacci(n - 1);  // create a new task to compute n-1
         f1.fork();                            // schedule to run asynchronously
         Fibonacci f2 = new Fibonacci(n - 2);  // create a new task to compute n-2
         return f2.invoke() + f1.join();       // wait for both tasks to compute.
           // f2 is run as part of this task, f1 runs asynchronously. 
           // (you could create two separate tasks and wait for them both, but running
           // f2 as part of this task is a little more efficient.
       }
     }
    

    然后你运行这个任务并得到结果

    // default parallelism is number of cores
    ForkJoinPool pool = new ForkJoinPool(); 
    Fibonacci f = new Fibonacci(100);
    int result = pool.invoke(f);
    

    这是一个简单的例子。在实践中,性能不会那么好,因为与任务框架的开销相比,任务执行的工作是微不足道的。根据经验,一个任务应该执行一些重要的计算 - 足以使框架开销微不足道,但又不会导致在运行一项大型任务的问题结束时有一个内核。将大型任务拆分为较小的任务可确保一个内核不会在其他内核空闲时做大量工作 - 使用较小的任务会使更多内核保持忙碌,但不会小到该任务没有实际工作。

    [...] 或者什么时候代码看起来很奇怪 您需要复制所有内容 以及推动了多少 到游泳池上。

    只有任务本身被推送到池中。理想情况下,您不想复制任何内容:为了避免干扰和锁定的需要,这会减慢您的程序,理想情况下,您的任务应该使用独立数据。只读数据可以在所有任务之间共享,不需要复制。如果线程需要合作构建一些大型数据结构,最好将它们单独构建,然后在最后将它们组合起来。组合可以作为一个单独的任务完成,或者每个任务都可以将它的一部分添加到整体解决方案中。这通常确实需要某种形式的锁定,但如果任务的工作量远大于更新解决方案的工作量,这不是一个相当大的性能问题。 My Knight's Tour 解决方案采用这种方法来更新板上的通用旅行存储库。

    与常规单线程编程相比,处理任务和并发性是一个相当大的范式转变。通常有几种设计可以解决给定的问题,但只有其中一些适合线程解决方案。可能需要几次尝试才能了解如何以多线程方式重铸熟悉的问题。最好的学习方法是查看示例,然后自己尝试。始终分析和测量不同线程数的影响。您可以在池构造函数中显式设置要在池中使用的线程(核心)数。当任务被线性分解时,随着线程数量的增加,您可以预期接近线性的加速。

    【讨论】:

      【解决方案2】:

      使用声称可以解决无法解决的“框架”(最佳任务调度是 NP 困难)根本不会帮助您 - 阅读书籍和有关并发算法的文章会。所谓的“任务”只不过是定义问题可分性(可以相互独立计算的部分)的花哨名称。 可分离问题的类别非常少 - 而且它们已经在旧书中有所介绍。

      对于不可分离的问题,您必须计划阶段和阶段之间的数据屏障以交换数据。 为同时数据交换优化数据屏障不仅是 NP 困难,而且不可能在原则上的一般方式 - 你需要检查所有可能的交错的历史 - 这就像已经指数集的幂集(比如在数学中从 N 到 R )。我提到的原因是要明确没有软件可以为您做到这一点,并且如何做到这一点本质上取决于实际算法以及并行化是否可行(即使理论上可行)的成败。

      当您进入高并行度时,您甚至无法维护队列,甚至不再拥有内存总线 - 想象一下 100 个 CPU 尝试在单个共享 int 上同步或尝试进行内存总线套利.您必须预先计划和预先配置要运行的所有内容,并在白板上基本上证明其正确性。英特尔的线程构建模块是那个世界的小孩子。它们适用于仍然可以共享内存总线的少量内核。运行可分离的问题是不费吹灰之力的,你可以在没有任何“框架”的情况下完成。

      因此,您又不得不尽可能多地阅读不同的并行算法。研究一个问题的近似最优数据屏障布局通常需要 1-3 年。当您在单个芯片上使用 16 个以上内核时,它就变成了布局,因为只有第一个邻居才能有效地交换数据(在一个数据屏障周期内)。因此,通过查看 CUDA 以及使用 IBM 的实验性 30 核 CPU 的论文和结果,您实际上会学到更多,而不是英特尔的推销或一些 Java 玩具。

      注意演示问题,因为浪费的资源(内核和内存的数量)比它们实现的加速要大得多。如果需要 4 个内核和 4 倍 RAM 才能以 2 倍的速度解决问题,则该解决方案无法进行并行化扩展。

      【讨论】:

        猜你喜欢
        • 2017-12-20
        • 2012-01-09
        • 2017-10-07
        • 2018-05-04
        • 2013-07-28
        • 2022-11-26
        • 1970-01-01
        • 1970-01-01
        • 2021-08-09
        相关资源
        最近更新 更多