skip to Main Content

i’m doing an artificial intelligence training and that method takes to long (5 minutes) and while my method is running my backend stay blocked waiting my method finish, is there any solution for it?

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

Answers


  1. As https://stackoverflow.com/users/740553/mike-pomax-kamermans noted, Javascript is single threaded, meaning long running synchronous operations will block your thread while executing. It’s not clear what library you’re using to perform your training, but check to see if they have any asynchronous methods for training. Also, you’re using the synchronous version of the fs.writeFile method, which again will block your thread while executing. To remedy this, use the async version:

    fs.writeFile(`${path}/trained-net.js`, `${net.toFunction().toString()};`, function (err) {
      if (err) return console.log(err);
      console.log('File write completed');
    }););
    
    Login or Signup to reply.
  2. Use child_process to perform training on a separate process. Here is how it can be implemented:

    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 */ }
    

    So when you call train on trainMaster.js from your main application it doesn’t do actual training and doesn’t block the event loop. Instead it creates a new process, waits for it to perform all the heavy lifting and then terminates it.

    This approach should work fine if the number of simultaneous trainings is less than the number of CPU on your machine. From Node.js docs:

    It is important to keep in mind that spawned Node.js child processes are independent of the parent with exception of the IPC communication channel that is established between the two. Each process has its own memory, with their own V8 instances. Because of the additional resource allocations required, spawning a large number of child Node.js processes is not recommended.

    Otherwise you will need some different approach, like spreading workers across multiple machines and using message queue to distribute the work between them.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search