The communication between my main thread and the webworker was really slow, so I took a look at this question which told me to how to use buffers to make the communication speed almost seemingless.
An answer to that question has communication of 0.4ms for an array containing 90000000
elements of the same kind as in my example.
The code is evaluating genomes in a neuroevolution algorithm set up with Neataptic to see how well their performing on the MNIST dataset, but it shouldn't be part of the problem.
I simply have an array with just 397000
elements, and the communication time varies between 30 and 50ms. This is a JSFiddle of my code (open console) - also below 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 is so slow in my code and not in the other questions code?
Edit: when I increase the amount of workers to start, the first arrival of a message will be after the last departure of a message... it seems like the webworkers don't start running after all the messages have been posted