【问题标题】:Node.js main thread blockingNode.js 主线程阻塞
【发布时间】:2018-08-10 12:29:08
【问题描述】:

我正在进行人工智能培训,该方法需要很长时间(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!'
                });
            });
        }
  }

【问题讨论】:

  • 在单独的进程中运行任何长时间。看看fork,如果你需要运行一些需要几到几百毫秒的东西。在单独的线程/进程中显式运行它们,因为 Node.js 与所有 JS 引擎一样 - 本质上是单线程的。

标签: node.js multithreading blocking brain.js


【解决方案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 进程。

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

【讨论】:

    【解决方案2】:

    正如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');
    }););
    

    【讨论】:

      猜你喜欢
      • 2015-07-06
      • 2011-10-18
      • 1970-01-01
      • 2018-02-16
      • 1970-01-01
      • 2015-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多