【问题标题】:Would it be faster to iterate over a giant array in parallel or synchronously?并行或同步迭代一个巨大的数组会更快吗?
【发布时间】:2014-08-08 20:05:09
【问题描述】:

给定一个巨大的阵列和单核机器,并行或顺序迭代阵列会更快吗?假设在迭代过程中没有完成任何工作,它实际上只是对数组进行迭代。

我的直觉说按顺序执行会更快,但我无法以我对操作系统和处理器的了解来证明这个答案是正确的。似乎无论哪种方式都必须完成相同数量的工作,但并行执行会导致上下文切换的额外复杂性。

这个问题的真实世界扩展是javascript的forEach方法。 Native forEach 同步执行其回调

var a = [1,2,3,4,5,6...100000000000000];
a.foreach(function(number) {
    // do computationally expensive, synchronous operation eg lots of additions/multiplications
});
console.log('done iterating through for loop and doing all of the work')

对上述代码使用异步版本的 forEach 会有好处吗(尤其是考虑到 js 只能使用单核)?

如果我们用异步工作做同样的问题,一旦阻塞操作发生,forEach 回调就会变成异步的。

var a = [1,2,3,4,5,6...100000000000000];
a.foreach(function(number) {
    // do asynchronous work, eg access to filesystem
    $.ajax({
        url: 'http://google.com',
        success: function() {
            console.log('suceeded for ' + number)
        })
});
console.log('done iterating through for loop but not with all async operations')

在这种情况下,使用 forEach 的异步版本是否有优势? 似乎我们已经通过仅切换到 IO 来更好地利用同步版本中的 CPU在我们启动 io 之前进行切换。

【问题讨论】:

  • 你尝试过基准测试吗?
  • 我没有 - 我想知道在我运行它的任何特定硬件上的理论答案而不是实际答案

标签: javascript concurrency parallel-processing


【解决方案1】:

只要您使用单核,执行某种并行操作就没有任何优势。您是正确的,设置多个任务/线程会对每个任务/线程产生一定的开销。并且跨并行操作分时共享单个内核会在每个任务切换上产生开销。顺序迭代没有这样的开销。唯一对并行操作具有优势的情况是当您拥有多个内核时。

现代 CPU 都是流水线的,其中大多数都是超标量引导。但是尝试某种并行操作不会“打包管道”或填充超标量单元。我不知道那里有任何 Javascript 引擎可以做到这一点。

哦,为了记录,你最好使用 for 循环而不是 foreach。简单的原因是 foreach 必须在每次传递时调用一个函数,即使它是一个匿名函数。调用函数会产生一定的开销。 for 循环,其中函数的内容被内联到循环体中,不会有这样的开销。这在其他论坛上已被广泛讨论,但我自己的经验证实了这一事实。

【讨论】:

【解决方案2】:

这完全取决于代码(很高兴您提供了该代码)。所以第一个问题的答案是。对于第二个问题这取决于

如果代码在单核机器同步版本中是全 CPU 绑定的,会快一点。如果有任何IO绑定代码异步版本在同一台机器上会更快。因为访问 IO 不处理 CPU。

只有在多核机器上,cpu 绑定的代码在异步模式下运行会更快。 IO 绑定代码仍将比其同步姐妹运行得更快。

这是一张夏季餐桌,

type                                  cpu bound   io bound   mixed
-------------------------------------------------------------------
single-core synchronous               normal      slower     slower
single-core asynchronous              normal      faster     faster
multi-core synchronous                normal      slower     slower
multi-core asynchronous               faster      faster     faster

注意事项:

  1. 假设在一次迭代中运行的所有代码不相互依赖。
  2. 在大多数实际用例中,我们要并行化的代码是 IO 和 CPU 的混合体。
  3. 很难区分 IO 绑定和 CPU 绑定部分

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多