ONNX Runtime Web (ORT Web) предоставляет возможность запускать модели машинного обучения прямо в браузере. Для сложных моделей и больших объёмов данных основной поток исполнения может блокироваться, что негативно влияет на отзывчивость интерфейса. Решением является использование Web Worker — отдельного потока исполнения JavaScript, позволяющего переносить ресурсоёмкие вычисления вне основного потока.
Web Worker создаётся через объект Worker, которому
передаётся путь к скрипту. Внутри воркера доступ к DOM отсутствует,
поэтому взаимодействие с основным потоком происходит исключительно через
передачу сообщений с помощью postMessage и
обработку событий onmessage.
Пример создания воркера:
const worker = new Worker('onnx-worker.js');
worker.onmess age = (event) => {
console.log('Результат из воркера:', event.data);
};
worker.postMessage({ command: 'runModel', inputData: inputArray });
Внутри файла onnx-worker.js содержатся вычисления с
моделью ONNX Runtime Web:
importScripts('https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js');
onmess age = async (event) => {
const { command, inputData } = event.data;
if (command === 'runModel') {
const session = await ort.InferenceSession.create('model.onnx');
const tensor = new ort.Tensor('float32', inputData, [1, inputData.length]);
const feeds = { input: tensor };
const results = await session.run(feeds);
postMessage(results.output.data);
}
};
Создание сессии —
ort.InferenceSession.create(path) возвращает объект сессии,
через который выполняются инференсы. В Web Worker сессия создаётся один
раз и может использоваться многократно для нескольких вызовов модели,
что экономит ресурсы.
Формирование тензоров — входные данные
преобразуются в объект ort.Tensor. Важно корректно
указывать тип (float32, int32) и форму
(shape).
Выполнение модели — метод
session.run(feeds) принимает объект feeds, где
ключи соответствуют именам входных узлов модели. Метод возвращает промис
с результатами, что идеально сочетается с асинхронной природой
воркеров.
Web Worker не имеет прямого доступа к памяти основного потока. Поэтому для передачи больших массивов данных рекомендуется использовать Transferable Objects, чтобы избежать лишнего копирования:
const buffer = new Float32Array(inputData).buffer;
worker.postMessage({ command: 'runModel', buffer }, [buffer]);
В воркере:
const inputArray = new Float32Array(event.data.buffer);
Это позволяет значительно ускорить передачу данных, особенно при работе с изображениями или аудио в виде массивов.
Часто возникает необходимость запускать несколько инференсов подряд.
В воркере реализуется очередь запросов через массив
промисов или обработку событий onmessage с
идентификаторами:
let requestId = 0;
const pendingRequests = new Map();
worker.onmess age = (event) => {
const { id, result } = event.data;
pendingRequests.get(id)?.resolve(result);
pendingRequests.delete(id);
};
function runModelInWorker(inputData) {
return new Promise((resolve) => {
const id = requestId++;
pendingRequests.set(id, { resolve });
worker.postMessage({ command: 'runModel', id, inputData });
});
}
Такой подход позволяет безопасно управлять параллельными запросами к воркеру и обрабатывать результаты по мере готовности.
Использование WebAssembly (WASM) — основной движок ORT Web работает через WASM, что обеспечивает переносимость и высокую производительность.
Предзагрузка модели — сессия создаётся один раз при инициализации воркера, что исключает повторную загрузку модели при каждом запросе.
Выбор подходящего бэкенда — ORT Web поддерживает WebGL и WebAssembly. В воркере WebGL может работать только в случае OffscreenCanvas, поэтому для большинства задач лучше использовать WASM.
Минимизация передачи данных — передавать только необходимый буфер, использовать Transferable Objects, избегать копирования больших массивов.
В сложной веб-приложении, где требуется обработка потокового видео, воркер позволяет выполнять инференс кадр за кадром, не блокируя интерфейс:
const videoFrame = getVideoFrame(); // Float32Array
const result = await runModelInWorker(videoFrame);
processResult(result); // обновление UI
Все ресурсоёмкие операции (предобработка кадра, инференс, постобработка) выполняются в отдельном потоке, что сохраняет плавность интерфейса и снижает нагрузку на главный поток.
Использование Web Worker с ONNX Runtime Web позволяет разделять вычислительные задачи и интерфейс, повышая отзывчивость приложений. Архитектура с одной предзагруженной сессией, очередью запросов и передачей Transferable Objects обеспечивает максимальную производительность и стабильность при работе с моделями глубокого обучения в браузере.