给定一个巨大的数组和一个单核机器,并行或顺序迭代数组会更快吗?假设迭代过程中没有完成任何工作,它实际上只是在数组上进行迭代。
我的直觉告诉我,按顺序执行会更快,但我无法以我对操作系统和处理器的了解来证明答案的合理性。看起来无论哪种方式都必须完成相同数量的工作,但并行执行会给上下文切换带来额外的复杂性。
这个问题的现实世界扩展是 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 之前进行切换。
最佳答案
只要您使用单核,执行某种并行操作就没有任何优势。您是正确的,设置多个任务/线程会给每个任务/线程带来一定的开销。跨并行操作分时单个核心会在每个任务切换上产生开销。顺序迭代没有这样的开销。并行操作唯一具有优势的时候是当您拥有多个核心时。
现代 CPU 都是流水线式的,并且大多数都是超标量启动的。但是尝试某种并行运算并不会“填充管道”或填充超标量单元。我不知道有任何 Javascript 引擎可以做到这一点。
哦,郑重声明一下,使用 for 循环比使用 foreach 更好。原因很简单,foreach 必须在每次传递时调用一个函数,即使它是一个匿名函数。调用函数会产生一定的开销。 for 循环中,函数的内容内联到循环体中,因此不会有这样的开销。这在其他论坛上已引起广泛争论,但我自己的经验证实了这一事实。
关于javascript - 并行或同步迭代一个巨大的数组会更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25211434/