Node.js主线程阻塞

时间:2018-08-09 22:51:58

标签: node.js multithreading blocking brain.js

我正在接受人工智能培训,该方法耗时很长(5分钟),而当我的方法运行时,后端保持阻塞,等待方法完成,这有什么解决方案吗?

train: (answersIA, search, res) => {
        const path = `api/IA/${search.id}`;

        if (answersIA.length == 0) {
            return null;
        }
        else {
            answersIA = answersIA.filter(answer => answer.score);
            answersIA = answersService.setOutput(answersIA);
            answersIA = answersService.encodeAll(IAServiceTrain.adjustSize(answersIA));
            net.train(answersIA, {
                errorThresh: 0.005,
                iterations: 100,
                log: true,
                logPeriod: 10,
                learningRate: 0.3
            });
            mkdirp(path, (err) => {
                if (err) throw 'No permission to create trained-net file';
                fs.writeFileSync(`${path}/trained-net.js`, `${net.toFunction().toString()};`);
                res.json({
                    message: 'Trained!'
                });
            });
        }
  }

2 个答案:

答案 0 :(得分:1)

使用child_process对单独的流程进行培训。这是它的实现方式:

trainMaster.js

const fork = require('child_process').fork;

exports.train = (arguments, callback) => {
    const worker = fork(`${__dirname}/trainWorker.js`);

    worker.send(arguments);

    worker.on('message', result => {
      callback(result);
      worker.kill();
    });
}

trainWorker.js

process.on('message', arguments => {
  const result = train(arguments)
  process.send(result);
});

function train(arguments) { /* your training logic */ }

因此,当您从主应用程序在 trainMaster.js 上调用train时,它不会进行实际的训练,也不会阻止事件循环。相反,它创建一个新进程,等待它执行所有繁重的工作,然后终止它。

如果同时训练的数量少于计算机上的CPU数量,则此方法应该可以正常工作。来自Node.js文档:

  

请务必牢记,生成的Node.js子进程独立于父进程,但两者之间建立的IPC通信通道除外。每个进程都有自己的内存,并带有自己的V8实例。由于需要额外的资源分配,因此不建议生成大量子Node.js进程。

否则,您将需要一些不同的方法,例如将工作人员分布在多台计算机上,并使用消息队列在它们之间分配工作。

答案 1 :(得分:0)

正如https://stackoverflow.com/users/740553/mike-pomax-kamermans所述,Javascript是单线程的,这意味着长时间运行的同步操作将在执行时阻塞您的线程。目前尚不清楚您正在使用哪个库来进行培训,但是请检查它们是否具有用于培训的异步方法。另外,您正在使用fs.writeFile方法的同步版本,该方法将再次在执行时阻塞您的线程。要解决此问题,请使用异步版本:

fs.writeFile(`${path}/trained-net.js`, `${net.toFunction().toString()};`, function (err) {
  if (err) return console.log(err);
  console.log('File write completed');
}););