Массив популяций занимает nx*ny*9*4 байта и показывался шейдеру одной привязкой. dzn объявляет max_storage_buffer_binding_size = 128 МиБ, поэтому потолок выходил 3.73 млн узлов: 14 прогонов кампании из 115 падали на создании bind group, а на них приходится 70.7% её стоимости. Ограничена при этом ровно привязка: max_buffer_size у dzn 2047 МиБ. Поэтому тот же буфер теперь показывается девятью привязками, по одному направлению в каждой, и потолок поднимается до 33.5 млн узлов — самая крупная сетка кампании (4096x4096, 16.8 млн) проходит с запасом. Как устроено: * шаг между направлениями выровнен на 256 байт (dir_stride), потому что смещение привязки обязано быть кратно min_storage_buffer_offset_alignment; * обращения к популяциям в WGSL идут через fget/fset/pget/pset, а их тело генерируется под вариант (build_shader); * вариант выбирается по max_storage_buffer_binding_size адаптера — где предела нет, собирается прежний общий, без switch в аксессорах; * KBC2D_SPLIT_POPULATIONS=1 включает раздельные принудительно: иначе сверить два варианта на одной карте нечем. Проверено: * на одном драйвере оба варианта дают одно и то же — Cd 2.39486, energy_end 5.74813e-05; раздельный стоит 5.7% пропускной способности; * на сетке 2048x2048, где раздельные привязки и нужны, нативный прогон против контейнерного: energy_end расходится на 2.4e-07, enstrophy_end на 1.3e-07; * preflight в контейнере: 115 сценариев из 115, ни одного отказа (было 14); * 29 собственных тестов решателя зелёные. Образ опубликован как notbigghost/kbc2d:1.2.0 (он же latest). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
115 lines
6.5 KiB
YAML
115 lines
6.5 KiB
YAML
# Запуск решателя и кампании в WSL2 — там, где драйвера NVIDIA для Linux не существует.
|
||
#
|
||
# ЧЕМ ЭТОТ ФАЙЛ ОТЛИЧАЕТСЯ ОТ docker-compose.server.yml. Тот рассчитан на настоящий
|
||
# Linux-сервер: просит у Docker устройство через драйвер `nvidia`, а Vulkan-ICD внутрь
|
||
# подкладывает NVIDIA Container Toolkit. В WSL2 этого сделать нельзя в принципе —
|
||
# у NVIDIA там нет Linux-библиотеки Vulkan, карта отдаётся по протоколу WDDM через
|
||
# /dev/dxg. Отсюда и ошибка `could not select device driver "nvidia"`.
|
||
#
|
||
# Здесь NVIDIA-runtime не запрашивается ВООБЩЕ. Нужно ровно две вещи:
|
||
# * проброс /dev/dxg — сама видеокарта;
|
||
# * монтирование /usr/lib/wsl — там Microsoft держит libd3d12.so и libdxcore.so.
|
||
# Дальше работает dzn (Dozen) из образа: драйвер Mesa, транслирующий Vulkan в D3D12.
|
||
# Ни nvidia-container-toolkit, ни nvidia-ctk, ни правки в daemon.json не требуются.
|
||
#
|
||
# ВАЖНО, ПРОЧТИТЕ ДО ЗАПУСКА КАМПАНИИ. dzn сообщает о себе conformanceVersion 0.0.0.0,
|
||
# то есть набор тестов соответствия Vulkan не проходил. Поэтому порядок такой:
|
||
#
|
||
# docker compose -f docker-compose.wsl.yml --profile check run --rm vulkan # карта видна?
|
||
# docker compose -f docker-compose.wsl.yml --profile check run --rm parity # числа те же?
|
||
# docker compose -f docker-compose.wsl.yml --profile check run --rm calibrate # скорость какая?
|
||
# docker compose -f docker-compose.wsl.yml --profile check run --rm plan
|
||
# docker compose -f docker-compose.wsl.yml up -d
|
||
# docker compose -f docker-compose.wsl.yml logs -f
|
||
#
|
||
# Шаг parity — не формальность. Он гоняет вихрь Тейлора-Грина (есть точное решение) и
|
||
# стационарное обтекание цилиндра на CPU в f64 и на GPU, и сверяет числа. Если он не
|
||
# прошёл, кампанию запускать нельзя: результаты будет нечем защищать.
|
||
#
|
||
# Результаты складываются в ./out на хосте.
|
||
|
||
name: kbc2d
|
||
|
||
# ── общая часть всех сервисов ────────────────────────────────────────────────
|
||
x-kbc2d: &kbc2d
|
||
image: notbigghost/kbc2d:1.2.0
|
||
# Контекст сборки — каталог с этим файлом. Если образа нет ни локально, ни в реестре,
|
||
# достаточно `docker compose -f docker-compose.wsl.yml build`: доступ к Docker Hub
|
||
# для запуска не обязателен.
|
||
build:
|
||
context: .
|
||
args:
|
||
VERSION: "1.2.0"
|
||
pull_policy: missing
|
||
devices:
|
||
- /dev/dxg:/dev/dxg
|
||
volumes:
|
||
- ./out:/work/bench/out
|
||
# Только на чтение: контейнеру нужны отсюда libd3d12.so, libd3d12core.so и
|
||
# libdxcore.so. Каталог наполняет сам WSL из C:\Windows\System32\lxss\lib.
|
||
- /usr/lib/wsl:/usr/lib/wsl:ro
|
||
environment:
|
||
# Без этого dzn не найдёт D3D12 и молча не даст ни одного адаптера.
|
||
LD_LIBRARY_PATH: /usr/lib/wsl/lib
|
||
# Осознанное согласие считать на драйвере, не прошедшем тесты соответствия Vulkan.
|
||
# Без этой переменной wgpu прячет dzn и решатель сообщает, что адаптер не найден.
|
||
# Прежде чем запускать кампанию, обязательно пройдите профиль parity.
|
||
WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER: "1"
|
||
# Оценки в часах драйвер считает из этих чисел. Умолчания взяты с другой машины —
|
||
# подставьте сюда то, что напечатает профиль calibrate.
|
||
KBC2D_GPU_MLUPS: ${KBC2D_GPU_MLUPS:-1200}
|
||
KBC2D_CPU_MLUPS: ${KBC2D_CPU_MLUPS:-22}
|
||
|
||
services:
|
||
# ── сама кампания: единственный сервис, который поднимается по `up -d` ──────
|
||
campaign:
|
||
<<: *kbc2d
|
||
container_name: kbc2d-campaign
|
||
# --resume пропускает всё, у чего уже есть summary.json: перезапуск продолжает с
|
||
# места, а не начинает заново.
|
||
command: ["--resume"]
|
||
# on-failure, а НЕ unless-stopped: кампания завершается штатно с кодом 0, и политика
|
||
# «перезапускать всегда» после её окончания крутила бы контейнер вхолостую.
|
||
restart: on-failure:5
|
||
stop_grace_period: 30s
|
||
logging:
|
||
driver: json-file
|
||
options:
|
||
max-size: "50m"
|
||
max-file: "5"
|
||
|
||
# ── проверки перед запуском (профиль check, сами не поднимаются) ────────────
|
||
vulkan:
|
||
<<: *kbc2d
|
||
profiles: ["check"]
|
||
entrypoint: ["vulkaninfo"]
|
||
command: ["--summary"]
|
||
|
||
parity:
|
||
<<: *kbc2d
|
||
profiles: ["check"]
|
||
entrypoint: ["python3"]
|
||
command: ["parity.py"]
|
||
|
||
preflight:
|
||
<<: *kbc2d
|
||
profiles: ["check"]
|
||
entrypoint: ["python3"]
|
||
command: ["preflight.py"]
|
||
|
||
calibrate:
|
||
<<: *kbc2d
|
||
profiles: ["check"]
|
||
command: ["--calibrate"]
|
||
|
||
plan:
|
||
<<: *kbc2d
|
||
profiles: ["check"]
|
||
command: ["--dry-run"]
|
||
# ── если результаты нужны не под root ────────────────────────────────────────
|
||
# Контейнер работает от root, поэтому файлы в ./out окажутся root:root. Чтобы они
|
||
# принадлежали вам, добавьте в x-kbc2d строку
|
||
# user: "${UID}:${GID}"
|
||
# и запускайте как UID=$(id -u) GID=$(id -g) docker compose -f ... up -d
|
||
# (каталог ./out при этом должен быть создан заранее и принадлежать вам).
|