Какие существуют методологии параллельных вычислений?
Что проверяют
Отличаете ли вы конкурентность от параллелизма и знаете ли, как в браузере получить настоящий параллелизм при однопоточном JavaScript. Следом обычно спрашивают, что вы вынесли бы в воркер в своём проекте и во что это обойдётся.
Как отвечать
Коротко про общую теорию, чтобы показать словарь:
- параллелизм по данным: одна операция над разными частями данных, SIMD, шейдеры на GPU;
- параллелизм по задачам: разные задачи идут одновременно на разных ядрах;
- общая память или обмен сообщениями: потоки делят данные и синхронизируются, либо живут изолированно и пересылают сообщения;
- конвейер и «разделяй и властвуй»: этапы или подзадачи раздаются исполнителям, результаты собираются.
Затем главное, про браузер. Event loop с async/await и Promise.all даёт конкурентность: пока ждём сеть, поток свободен, но код выполняется по очереди на одном потоке. Параллелизм дают отдельные механизмы:
- Web Workers: отдельный поток без доступа к DOM, связь через
postMessage. Данные копируются через structured clone, аArrayBufferможно передать без копирования как transferable; SharedArrayBufferиAtomics: общая память между потоками. Доступны только в режиме cross-origin isolation, с заголовкамиCross-Origin-Opener-Policy: same-originиCross-Origin-Embedder-Policy;- WebAssembly с потоками: построены на том же
SharedArrayBuffer; - GPU: WebGL и compute-шейдеры WebGPU для массовых вычислений;
OffscreenCanvas: отрисовка графики внутри воркера.
Для удобства часто берут Comlink: он превращает postMessage в обычные вызовы функций.
Где спотыкаются
Называют Promise.all параллельным выполнением. Запросы ждут ответа одновременно, но JavaScript при этом работает в одном потоке.
Выносят в воркер мелкие задачи. Копирование больших объектов через postMessage может стоить дороже самих вычислений.
Включают SharedArrayBuffer без заголовков изоляции и не понимают, почему он undefined. Заодно забывают, что эти заголовки ломают встраивание сторонних ресурсов без CORP или CORS.