在Node.js中并行化任务

Jer*_*auw 29 javascript parallel-processing multithreading asynchronous node.js

我想在JS中做一些资源密集的任务.对于这个问题,我们假设它们是一些繁重的计算,而不是系统访问.现在我想同时运行任务A,B和C,并在完成后执行一些功能D.

异步库为此提供了一个很好的脚手架:

async.parallel([A, B, C], D);
Run Code Online (Sandbox Code Playgroud)

如果我正在做的只是计算,那么它仍将同步运行(除非库将任务放在不同的线程上,我预计不是这种情况).我该如何让它实际上是平行的?通常由异步代码完成的事情是什么,以阻止调用者(使用NodeJS时)?它是否开始了儿童过程

Mat*_*elf 40

我该如何让它实际上是平行的?

首先,在单节点应用程序中,您不会真正并行运行.节点应用程序在单个线程上运行,并且节点的事件循环一次只处理一个事件.即使在多核盒上运行,您也无法在节点应用程序中获得处理的并行性.

也就是说,您可以通过将代码分叉到单独的节点进程通过生成子进程来处理多核机器上的并行性.实际上,这允许您创建节点本身的多个实例,并以不同的方式与这些进程通信(例如,stdout,进程分支IPC机制).此外,您可以选择将功能(通过职责)分离到他们自己的节点应用程序/服务器中,并通过RPC调用它.

通常由异步代码完成的事情是什么,以阻止调用者(使用NodeJS时)? 它是否开始了儿童过程?

它没有开始一个新的过程.在下面,当在node.js中使用async.parallel时,它正在使用process.nextTick().而nextTick()允许您通过将工作推迟到新堆栈来避免阻塞调用者,以便您可以交错cpu密集型任务等.

长话短说

Node不会轻易"开箱即用"来实现多处理器并发.Node改为为您提供非阻塞设计和利用线程而不共享内存的事件循环.多个线程无法共享数据/内存,因此不需要锁定.节点是免费的.一个节点进程利用一个线程,这使得节点既安全又强大.

当您需要在多个进程之间拆分工作时,请使用某种消息传递与其他进程/服务器进行通信. 例如IPC/RPC.


欲了解更多信息:

来自SO的什么是Node.js的惊人答案...有很多善良.

了解process.nextTick()


Jos*_*len 14

异步和并行不是一回事.异步意味着您不必等待同步.并行意味着您可以同时执行多项操作.Node.js只是异步的,但它只有1个线程.它一次只能处理1件事.如果你有一个长时间运行的计算,你应该启动另一个进程,然后让你的node.js进程异步等待结果.

为此,您可以使用child_process.spawn,然后从stdin读取数据.

http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options

var spawn = require('child_process').spawn;
var process2 = spawn('sh', ['./computationProgram', 'parameter'] );

process2.stderr.on('data', function (data) {
    //handle error input
});

process2.stdout.on('data', function (data) {
    //handle data results
});
Run Code Online (Sandbox Code Playgroud)


wpr*_*prl 6

请记住,I/O 是由 Node.js 并行化的;只有您的 JavaScript 回调是单线程的。

假设您正在编写一个服务器,添加生成过程或分叉的复杂性的另一种方法是简单地构建无状态节点服务器并在每个内核上运行一个实例,或者更好地在它们自己的虚拟化微服务器中运行多个实例。使用反向代理或负载平衡器协调传入请求。

您还可以将计算卸载到另一台服务器,可能是 MongoDB(使用 MapReduce)或 Hadoop。

要真正成为硬核,您可以用 C++ 编写一个 Node 插件,并对并行化计算代码进行细粒度控制。无论如何,C++ 的加速可能会否定并行化的需要。

您始终可以使用最适合数值计算的另一种语言编写代码来执行计算密集型任务,例如通过 REST API 公开它们。

最后,您也许可以node-cuda根据计算类型使用或类似的东西在 GPU 上运行代码(并非所有都可以针对 GPU 进行优化)。

是的,你可以 fork 并产生其他进程,但在我看来,node 的主要优点之一是不必担心并行化和线程化,因此完全绕过了大量的复杂性。