代码之家  ›  专栏  ›  技术社区  ›  user3516604

Node.js主线程阻塞

  •  0
  • user3516604  · 技术社区  · 7 年前

    我正在做一个人工智能训练,这个方法需要很长的时间(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 回复  |  直到 7 年前
        1
  •  1
  •   danroshko    7 年前

    使用 child_process 在一个单独的过程中进行训练。以下是它的实现方法:

    列车长.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();
        });
    }
    

    列车员.js

    process.on('message', arguments => {
      const result = train(arguments)
      process.send(result);
    });
    
    function train(arguments) { /* your training logic */ }
    

    所以当你打电话 train 列车长.js 从主应用程序来看,它不进行实际的训练,也不会阻塞事件循环。相反,它创建一个新进程,等待它执行所有繁重的工作,然后终止它。

    如果同时训练的数量小于计算机上的CPU数量,这种方法应该可以正常工作。从Node.js文档:

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

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

        2
  •  0
  •   willascend    7 年前

    作为 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');
    }););