The transition between the main thread and the web worker is slow

Communication between my main thread and the webmaster was very slow, so I considered this question , which described how to use buffers for communication, the speed is almost apparent.

The answer to this question is 0.4 ms for an array containing elements of 90000000the same type as in my example.

The code evaluates the genomes in the neuroevolution algorithm installed with Neataptic to see how well they perform in the MNIST dataset, but it should not be part of the problem.

I just have an array with only 397000elements, and the communication time varies from 30 to 50 ms. This is the JSFiddle of my code (open console) - also here:

/** Rename vars */
var Neat    = neataptic.Neat;
var Methods = neataptic.Methods;
var Config  = neataptic.Config;

/** Turn off warnings */
Config.warnings = false;

function createWorker(network, cost){
  // source is equivalent of test(), but without time recording
  var source = `
  ${network.standalone()}

  var cost = ${cost.toString()}
  onmessage = function(e) {
    console.log('Message received at', performance.now());
    var set = new Float64Array(e.data);
    var ins = set[0];
    var out = set[1];

    var error = 0;
    // Calculate how much samples are in the set
    for(var i = 0; i < (set.length - 2) / (ins + out); i++){
      let input = [];
      let target = [];
      for(var j = 2 + i * (ins + out); j < 2 + i * (ins + out) + ins; j++){
        input.push(set[j]);
      }
      for(var j = 2 + i * (ins + out) + ins; j < 2 + i * (ins + out) + ins + out; j++){
        target.push(set[j]);
      }

      let output = activate(input);
      error += cost(target, output);
    }

    var answer = new Float64Array([error / ((set.length - 2) / (ins + out))]);
    postMessage(answer.buffer, [answer.buffer]);
  }
  `;

  var blob = new Blob([source]);
  var blobURL = window.URL.createObjectURL(blob);
  var worker = new Worker(blobURL);

  return worker;
}

async function multiEvaluate(population, dataSet, cost){
  // Prepare the dataset to create a buffer
  var converted = [dataSet[0].input.length, dataSet[0].output.length];

  for(var i = 0; i < dataSet.length; i++){
    for(var j = 0; j < converted[0]; j++){
      converted.push(dataSet[i].input[j]);
    }
    for(var j = 0; j < converted[1]; j++){
      converted.push(dataSet[i].output[j]);
    }
  }

  return new Promise((resolve, reject) => {
    // Keep track of how many workers are finished
    var counter = 0;

    // Create a worker for every network, post a message
    for(var i = 0; i < population.length; i++){
      let genome = population[i];
      let worker = createWorker(genome, cost);
      worker.onmessage = function(e){
        genome.score = new Float64Array(e.data)[0];
        worker.terminate();
        if(++counter == population.length){
          resolve()
        }
      }

      let temp = new Float64Array(converted);
      console.log('Message sent at', performance.now());
      worker.postMessage(temp.buffer, [temp.buffer]);
    }
  });
}

async function f() {
  var network= new neataptic.Network(784,10);

  for(var i = 0; i < network.connections.length; i++){
    network.connections[i].weight = Math.random() * .02 - .01;
  }

  var neat = new neataptic.Neat(784, 10, null, {popsize: 1, network: network});
  for(var i = 0; i < 10; i++) neat.mutate();

  var set = mnist.set(500, 0).training;
  await multiEvaluate(neat.population, set, Methods.Cost.MSE);
}

f();

Does anyone know why the communication time in my code is so slow and not in another question code?

Edit: when I increase the number of workers to start, the first arrival of the message will be after the last message was sent ... it looks like web users do not start after all messages have been sent

+4
source share

Source: https://habr.com/ru/post/1680561/


All Articles