Parallel processing 如何编写任务?(并行代码)

Parallel processing 如何编写任务?(并行代码),parallel-processing,tbb,Parallel Processing,Tbb,我对英特尔线程构建块印象深刻。我喜欢我应该如何编写任务而不是线程代码,我喜欢它如何在我有限的理解下工作(任务在一个池中,4个线程上不会有100个线程,一个任务不能保证运行,因为它不在自己的线程上,并且可能在池中很远。但是它可能与另一个相关任务一起运行,所以你不能做像典型的线程不安全代码这样的坏事) 我想了解更多关于编写任务的信息。我喜欢这里的“基于任务的多线程-如何为100个内核编程”视频(目前是最后一个链接。警告这不是“很棒”)。我最喜欢的部分是“解决迷宫最好是并行完成”,大约48分钟(你可以

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

我想了解更多关于编写任务的信息。我喜欢这里的“基于任务的多线程-如何为100个内核编程”视频(目前是最后一个链接。警告这不是“很棒”)。我最喜欢的部分是“解决迷宫最好是并行完成”,大约48分钟(你可以点击左边的链接。如果有的话,那部分就是你需要关注的全部内容)


然而,我喜欢看到更多的代码示例和一些如何编写任务的API。有人有好的资源吗?我不知道将一个类或一段代码推到池中后会是什么样子,也不知道当您需要复制所有内容以及有多少内容被推到池中时,代码会有多奇怪。

Java有一个并行任务amework类似于线程构建块——它被称为Fork-Join框架。它用于当前的JavaSE6,并将包含在即将到来的JavaSE7中

除了javadoc类文档之外,还有一些资源可用于开始使用该框架 还有一个wiki,其中包含这些类的其他文档、注释、建议、示例等

例如矩阵乘法是一个很好的起点

我使用fork-join框架解决了其中的一些问题。该框架轻量级且开销较低-我是Kight’s Tour问题的唯一Java条目,它在竞争中的表现优于其他条目。Java源代码和writeup可从challenge站点下载

编辑:

我不知道一节课或一首曲子 在将代码推到 游泳池[……]

您可以通过对其中一个子类进行子类化来创建自己的任务,例如。下面是如何并行计算斐波那契序列。(摘自
RecursiveTask
javadocs-注释是我的。)

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

[…]或者当 你需要把所有的东西都复制一份 每件事有多少是被推的 在游泳池里

只有任务本身被推送到池中。理想情况下,您不希望复制任何内容:为了避免干扰和需要锁定(这会降低程序的速度),您的任务最好使用独立的数据。只读数据可以在所有任务之间共享,并且不需要复制。如果线程需要合作在构建一些大型数据结构时,最好是分别构建各个部分,然后在最后进行组合。组合可以作为单独的任务来完成,或者每个任务都可以将自己的一部分添加到整体解决方案中。这通常需要某种形式的锁定,但如果任务的工作正常,则性能问题不大比更新解决方案的工作量大得多。My Knight's Tour解决方案采用这种方法来更新板上的一个常见的tours存储库

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

玩声称解决不可解决问题的“框架”(最佳任务调度是NP难的)这对你一点帮助都没有——阅读关于并行算法的书籍和文章会有帮助。所谓的“任务”只不过是定义问题可分性(可以独立计算的部分)的花哨名称而已.可分离问题的类别非常小,它们已经在旧书中介绍过了。

对于不可分离的问题,您必须规划阶段和阶段之间的数据屏障以交换数据。同步数据交换的数据屏障的优化编排不仅是NP难的,而且原则上不可能以一般方式解决-您需要检查所有可能交错的历史-这就是li我提到的原因是,没有任何软件可以为你做到这一点,如何做到这一点本质上取决于实际的算法和并行化是否可行的成败(即使在理论上是可能的)

当您进入高并行时,您甚至无法维护队列,甚至不再有内存总线——想象一下,100个CPU试图在单个共享int或tryi上同步
 // 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);