如何使用并行subprocess在大型数组上执行“工作”?
我有一大堆数字。 我想要使用JavaScript / Node.js来计算所有数字的总和。 (就这个问题而言,这是一个简单的总和;实际上我有一个更复杂和更冗长的math运算来执行)。
在单线程的世界中,计算总和需要很长时间。 为了更快速地处理结果,我一直在尝试将工作委托给多个并行运行的subprocess。 每个subprocess确定一个子数组的总和,并且在父进程中总计一切。
我的两个脚本如下:
index.js
function computeSum(data) { var start = new Date(); var sum = data.reduce(function(a, b) { return a + b; }); console.log("Sum = %s, Time = %s ms", sum, new Date().getTime() - start.getTime()); } function computeSumConcurrent(data) { var child_process = require("child_process"); var os = require("os"); var cpuCount = os.cpus().length; var subArraySize = data.length / cpuCount; var childProcessesFinished = 0; var start = new Date(); var sum = 0; for (var i = 0; i < cpuCount; i++) { var childProcess = child_process.fork("child.js"); childProcess.on("message", function(message) { sum += message.sum; childProcessesFinished++; if (childProcessesFinished == cpuCount) { console.log("Sum = %s, Time = %s ms", sum, new Date().getTime() - start.getTime()); process.exit(); } }); childProcess.send({ subArray: data.slice(subArraySize * i, subArraySize * (i + 1)) }); } } console.log("Populating array..."); var data = [] for (var i = 0; i < 50000000; i++) { data.push(Math.random()); } console.log("Computing sum without using child processes..."); computeSum(data); console.log("Computing sum using child processes..."); computeSumConcurrent(data);
child.js
process.on("message", function(message) { var sum = message.subArray.reduce(function(a, b) { return a + b; }); process.send({ sum: sum }); process.exit(); });
如果你运行index.js,你会发现并行总和非常慢。 我想这可能是由于childProcess.send
,这并不意味着要传递大量的数据 ,但我不完全确定。
那么这种事情的解决scheme是什么? 如何使并行总和比单线程更快?
创build用于小型工作的subprocess以及发送和接收消息实际上可以增加持续时间或处理,因为发送和接收消息需要时间。
还有一个问题,在你的代码中,你实际上是将subprocess从主进程本身分离出来,这不会让你的主进程免于工作,而只是增加它。
我会build议你另一种方法。
创build一个subprocess发送它的所有数据。
让孩子自己创造其他孩子,并给他们分配工作。 然后计算所有的结果。
将最终结果发送给父母。
注意:
确保你不要创造太多的孩子,并给他们分配很小的工作。 这只会让你发送和接收太多的消息,从而会延误处理。
也不要创造太less的孩子叉,他们自己需要太多时间处理给定的任务。
您必须确保任何subprocess在它自己创build的subprocess之前不会退出
优点:
- 你的主stream程不会忙于分工和计算结果。
- 很多分叉的孩子会在相对较短的时间内完成任务(我不会说很短的时间)
随意问你是否需要一些例子。