假设我有一块有 4 个 CPU 的主板。根据英特尔的说法,每个 CPU 都有 8 个内核/16 个线程。
现在,假设我有一些疯狂的字符串操作任务需要几天才能完成。有没有办法计算多少分叉和线程会产生最佳性能?我不确定我应该启动多少个分叉和线程。另外,我不确定启动线程是否会使我受益?
我对 Ruby 特别感兴趣,因为我不确定 Ruby 2 线程与例如 C++ 线程相比如何。
假设我有一块有 4 个 CPU 的主板。根据英特尔的说法,每个 CPU 都有 8 个内核/16 个线程。
现在,假设我有一些疯狂的字符串操作任务需要几天才能完成。有没有办法计算多少分叉和线程会产生最佳性能?我不确定我应该启动多少个分叉和线程。另外,我不确定启动线程是否会使我受益?
我对 Ruby 特别感兴趣,因为我不确定 Ruby 2 线程与例如 C++ 线程相比如何。
在 MRI Ruby 中,由于全局解释器锁 (GIL),在多个线程中运行受 CPU 限制的进程几乎没有好处,这实质上意味着每个 Ruby 进程在任何时候都只有一个用户级线程处于活动状态. JRuby 没有这个限制。
在 MRI Ruby 中,您可以通过使用单独的进程(通过)来完成并行工作Process.fork
。进程之间的通信比线程之间的通信开销更大,但如果一个问题很简单地并行化,那么这没什么大不了的。
这可能是(MRI)Ruby 和 C++ 之间的主要区别。然而,如果你有一个密集的编码过程,那么 Ruby 就不是首选语言——至少不是你希望解决的核心问题。用 C、C++ 或 Java 编写大部分处理可能更可取,使用 Ruby 可能用于编组输入和输出。这与线程模型无关,但是一个编写良好的 C 库可以比用纯 Ruby 编写的相同内容快 100 倍,如果您谈论的是使用 Ruby 在多个内核上花费一周的过程,那么投资使用不同的语言会得到很好的回报(要么只需要几个小时,要么你可以在同一时间或更短的时间内在单核上完成,而无需使用线程)
没有通用公式来确定有多少线程或进程最适合解决一个问题。在您能够最大限度地利用可用 CPU 之前,您可能会遇到管理开销、使用的总内存等方面的限制。您应该对性能进行基准测试。显然,可用内核的数量是一个重要因素,可能一个很好的猜测是从每个内核 1 个线程(或进程)开始。
这取决于您使用的算法的细节。真的没有什么普遍规律。
考虑如下任务:
现在,假设这个任务每小时移动 1,000 个小部件。如果添加第二辆卡车,您每小时将移动多少个小部件?好吧,您当然可以推断出每小时不会超过 2,000 个小部件。
为什么会少一些?那么,如果驾驶只需要一点点时间,而卡车花费大量时间等待装载机或卸载机与另一辆卡车一起完成,该怎么办?如果道路狭窄,卡车无法轻松绕行怎么办?
因此,为了知道,您必须了解算法正在使用哪些资源以及如何使用它们。一般来说,很难预测唯一现实的选择是测量。您可能会发现将算法更改为更好地并行化的算法是可能的。
经验法则:每个 CPU 线程有 1 个进程或操作系统线程。
对于 Ruby,至少是 MRI Ruby,这意味着每个 CPU 线程有 1 个 fork,因为 MRI Ruby 线程不能真正并行执行。