0

现代计算机的内核越来越多。我们想改变我们当前的线性算法来使用这些核心。

只有在有空闲处理器的情况下,拆分任何算法以使用不同的线程才有意义。

如果有免费处理器,是否有任何好的库可以帮助并行化某些步骤?

我会举一些例子。

  • 如果只有一个处理器,那么创建多个线程是没有意义的。它会降低速度。
  • 如果在一个核心二重奏上运行 2 个进程(服务器上的请求),那么启动线程也是没有意义的。
  • 如果核心二重奏上只有一个进程,那是有道理的。

抽象算法有 4 个步骤 A、B、C 和 D。步骤 A、B 和 C 可以并行执行。步骤 D 需要来自 A、B 和 C 的结果。

编辑:我的意思是一个数学算法。无 IO,无事件等

4

7 回答 7

4

这不一定是真的。

根据算法,即使只有一个内核可用,将其拆分为多个线程通常也是有意义的。如果套接字、IO 等有任何等待,您可以从中受益。如果有 2 个进程,则“其他”进程可能不会 100% 使用其他核心,因此线程在这里可以提供帮助。在这种情况下,请相信您的操作系统能够正确处理它。

您始终可以使用 Runtime.availableProcessors() 检查处理器计数,以确定如何将其拆分为单独的线程。或者,您可以使用线程池,它应该可以使用更多处理器正确扩展。

不过,总的来说,如果算法对并行化有意义,我会设计您的算法以使用多个处理器。大多数系统将有更多可用的内核/处理器,如果你发现它需要它,你可以随时调整你的实现。如果进程长时间运行,那么生成线程的开销将是值得的——如果它已经很快了,可能更值得寻找其他地方进行优化。

于 2009-03-14T20:55:02.850 回答
3

查看 Java 5 及更高版本中的各种并发类。您很可能需要一个 ThreadPoolExecutor - http://java.sun.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html

ThreadPool 的适当值很可能因系统而异,具体取决于工作负载和硬件架构。使其用户可调节。

于 2009-03-14T21:17:52.000 回答
1

对于一些想法,请查看JSR166 和 JSR166y(类似于带有工作窃取 (166) 和并行数组 (166y) 的分叉连接系统)。

一些不错的阅读和对 Java 未来方向的概述。看起来还不错(对高级并发和并行编程的强大支持)。

于 2009-03-14T20:55:58.667 回答
1

我经常有一个固定的线程池,它的线程数与处理器的数量动态相同(请参阅运行时)我将任务添加到这个线程池中,以便它使用所有可用的处理器。

我不认为您应该尝试在操作系统中重新发明进程调度程序。它做得很好,所以让它做它做得好的事情。

于 2009-03-14T21:15:29.867 回答
1

拥有比核心更多的线程/进程不一定是坏事。如果您的代码是严格数学的,几乎没有 I/O 并且没有副作用,那么是的,内核和线程之间的 1:1 对应关系是最佳的。但通常情况并非如此。与时钟周期相比,I/O 需要数亿年。当操作系统可以交换另一个线程以继续运行时,为什么要在等待 I/O 时完全停止内核?

问题是没有很多语言/编译器可以为您做出并发决定。您需要设计程序以利用并发性。而且您可能需要为多个目标环境设计程序,通常不受您的控制。因此,通常情况下,最佳实践是为任何有意义的事情创建线程以并行化并让线程调度程序处理它。应该调整线程调度程序以在特定硬件上使用,这比您针对“任何硬件出现”调整程序要好得多。

于 2009-03-14T21:36:20.723 回答
1

抽象算法有 4 个步骤 A、B、C 和 D。步骤 A、B 和 C 可以并行执行。步骤 D 需要来自 A、B 和 C 的结果。

这是使用 Ateji PX 表示法的单行代码,Java 语言的扩展:

[ A(); || B(); || C(); ]; D();

作为程序员,你的职责是表达哪里有可能并行执行,这就是双杠“||”的作用 在代码中。调度程序现在能够充分利用可用硬件,即在可用时在三个不同的内核上运行 A、B 和 C。

这是一个非常高级的视图,在 A、B 或 C 内部可能会展示更多的并行性。

于 2011-03-16T18:39:47.420 回答
0

我认为您需要来自 Javolution 的 ConcurrentContext 。请参阅http://javolution.org/target/site/apidocs/javolution/context/ConcurrentContext.html

于 2009-03-14T22:01:34.687 回答