WebWorkers — это технология браузеров, позволяющая выполнять скрипты в фоновом потоке, не блокируя основной поток интерфейса пользователя. В контексте нейронных сетей на JavaScript, особенно при работе с ConvNetJS, использование WebWorkers критически важно для повышения производительности и отзывчивости приложений, выполняющих вычислительно тяжёлые операции.
Создание нового воркера осуществляется через конструктор
Worker:
const worker = new Worker('worker.js');
Файл worker.js содержит код, который будет выполняться в
отдельном потоке. Важно понимать, что воркеры имеют
изолированное окружение: они не имеют доступа к DOM,
глобальным переменным основного потока и некоторым объектам браузера.
Все данные между основным потоком и воркером передаются через систему
сообщений (postMessage и onmessage), что
требует сериализации данных.
Передача больших массивов данных, например весов нейронной сети или батчей изображений, может быть узким местом. Использование Transferable Objects позволяет передавать массивы без копирования:
const buffer = new Float32Array([1, 2, 3, 4]);
worker.postMessage(buffer.buffer, [buffer.buffer]);
После передачи buffer в основном потоке становится
недоступным, что предотвращает дублирование памяти и ускоряет
работу.
ConvNetJS — это библиотека для создания и обучения нейронных сетей
полностью на JavaScript. Она предоставляет объекты Vol,
Net, Trainer и методы для прямого
распространения (forward) и обратного распространения
(backward). Использование WebWorkers позволяет выполнять
обучение и предсказания на фоне, освобождая основной поток для
обновления интерфейса и визуализации.
worker.js:
importScripts('convnetjs.js');
let net = new convnetjs.Net();
let layer_defs = [
{type:'input', out_sx:28, out_sy:28, out_depth:1},
{type:'fc', num_neurons:100, activation:'relu'},
{type:'softmax', num_classes:10}
];
net.makeLayers(layer_defs);
let trainer = new convnetjs.SGDTrainer(net, {learning_rate:0.01, momentum:0.9, batch_size:10});
onmess age = function(e) {
const {data, type} = e.data;
if(type === 'train') {
data.forEach(sample => {
let x = new convnetjs.Vol(sample.input);
trainer.train(x, sample.label);
});
postMessage({type:'trained', status:'ok'});
} else if(type === 'predict') {
let x = new convnetjs.Vol(data.input);
let result = net.forward(x);
postMessage({type:'prediction', output: result.w});
}
};
Основной поток:
const worker = new Worker('worker.js');
worker.onmess age = function(e) {
const {type, output, status} = e.data;
if(type === 'trained') {
console.log('Обучение завершено', status);
} else if(type === 'prediction') {
console.log('Результат предсказания:', output);
}
};
worker.postMessage({type:'train', data:trainData});
worker.postMessage({type:'predict', data:{input:testInput}});
Для больших задач целесообразно использовать пул воркеров. Каждый воркер получает часть данных для обучения или предсказаний. Важные моменты:
const workers = [];
const numWorkers = 4;
for(let i=0; i<numWorkers; i++) {
workers.push(new Worker('worker.js'));
}
function distributeTraining(data) {
const chunkSize = Math.ceil(data.length / numWorkers);
workers.forEach((worker, i) => {
const chunk = data.slice(i*chunkSize, (i+1)*chunkSize);
worker.postMessage({type:'train', data:chunk});
});
}
Использование WebWorkers снижает задержку интерфейса, но вычислительные задачи остаются CPU-bound. Для максимальной производительности:
Float32Array и Transferable Objects для
передачи больших массивов.WebWorkers в сочетании с ConvNetJS обеспечивают возможность запуска полноценного обучения нейронной сети в браузере без блокировки интерфейса. Правильная организация потоков, управление данными и эффективная передача массивов позволяют достигать высокой производительности даже в ограниченных ресурсах браузера.