简体   繁体   English

并行或同步遍历巨型数组会更快吗?

[英]Would it be faster to iterate over a giant array in parallel or synchronously?

Given a giant array and a single core machine, would it be faster to iterate over the array in parallel or sequentially? 给定一个巨大的阵列和一个单核计算机,并行或顺序遍历阵列会更快吗? Assume no work is being done as part of the iteration, it's literally just iterating over the array. 假设在迭代过程中没有做任何工作,实际上只是迭代数组。

My gut says it would be faster to do sequentially, but I can't justify the answer with my knowledge of OSes and processors. 我的直觉说顺序执行会更快,但是我无法凭借我对操作系统和处理器的了解来证明答案。 It seems like the same amount of work must be done either way, but parallel execution would incur extra complexity for context switches. 似乎无论哪种方式都必须完成相同数量的工作,但是并行执行将为上下文切换带来额外的复杂性。

The real world extension of this question is javascript's forEach method. 这个问题的真实世界扩展是javascript的forEach方法。 Native forEach executes its callbacks synchronously 本机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')

Would it ever be advantageous to use an asynchronous version of forEach for the above code (especially given that js can only utilize a single core)? 为上述代码使用forEach的异步版本是否会更有利(特别是考虑到js只能使用一个内核)?

If we do the same problem but with asynchronous work, the forEach callbacks will become asynchronous as soon as the blocking operation occurs. 如果我们也做同样的问题但使用异步工作,则在发生阻塞操作后,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')

In this case, would it ever be advantageous to use an async version of forEach? 在这种情况下,使用forEach的异步版本会更有利吗? It seems like we're already taking better advantage of the CPU in the synchronous version by only switching for IO instead of switching before we even initiate the io. 似乎我们已经通过仅切换IO而不是在启动io之前进行切换而更好地利用了同步版本中的CPU。

So long as you're using a single core, there is NO advantage, ever, to doing some kind of parallel operations. 只要您使用单个内核,执行某种并行操作就永远没有优势。 You are correct that setting up multiple tasks/threads incurs a certain amount of overhead on each of them. 正确的是,设置多个任务/线程会给每个任务/线程带来一定的开销。 And time-sharing the single core across the parallel ops incurs an overhead on each task switch. 跨并行操作分时共享单个内核会增加每个任务切换的开销。 Iterating sequentially has no such overhead. 顺序迭代没有这种开销。 The only time you have an advantage to parallel ops is when you have multiple cores. 拥有并行内核的唯一优势就是拥有多个内核。

Modern CPUs are all pipelined and most of them are superscalar to boot. 现代的CPU都是流水线式的,而且大多数都是超标量启动。 But attempting some kind of parallel ops isn't going to "pack the pipeline" or fill the superscalar units. 但是,尝试某种并行操作不会“打包”或填充超标量单元。 I don't know that any Javascript engines out there can do that. 我不知道任何Javascript引擎都能做到这一点。

Oh, and just for the record, you'd be better off with a for loop than a foreach. 哦,仅作记录,使用for循环比使用foreach更好。 The simple reason is that foreach has to call a function on each pass, even if it's an anonymous function. 原因很简单,因为foreach必须在每次通过时都调用一个函数,即使它是一个匿名函数也是如此。 Calling a function incurs a certain amount of overhead. 调用函数会产生一定的开销。 A for loop, where the contents of the function are inlined into the body of the loop, will have no such overhead. 在for循环中,函数的内容被内联到循环的主体中,将没有这种开销。 This has been widely debated in other fora but my own experience bears out this fact. 在其他论坛上对此进行了广泛的辩论,但我的经验证明了这一事实。

It completely depends on the code (glad you have provided that). 它完全取决于代码(您提供的代码很高兴)。 So the answer to your first question would be No . 因此,第一个问题的答案是“ 否” And for second question It depends . 对于第二个问题, 这取决于

If the code is full CPU bound in a single core machine synchronous version will be a little bit faster. 如果代码是完整的,CPU绑定在单核计算机上,则同步版本会快一点。 If there is any IO bound code asynchronous version will be faster on the same machine. 如果有任何IO绑定代码,则异步版本将在同一台计算机上更快。 Because accessing IO doesn't deal with CPU. 因为访问IO不会处理CPU。

Only on a multi core machine, cpu bound code will run faster if they run in asynchronous mode. 仅在多核计算机上,如果cpu绑定代码以异步模式运行,它们将运行得更快。 IO bound code will still run faster than its synchronous sister. IO绑定代码仍将比其同步姐妹运行速度更快。

Here is a summery table, 这是一张夏日餐桌,

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

Notes: 笔记:

  1. Its assumed that all the code that runs on a single iteration is not dependent to each other. 它假定在​​一次迭代中运行的所有代码都不相互依赖。
  2. In most of the real-life use cases the code we want to parallelize is a mix of IO and CPU. 在大多数实际用例中,我们要并行化的代码是IO和CPU的混合。
  3. Its very hard to separate IO bound & CPU bound part 很难将IO绑定和CPU绑定分开

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM