# Запуск решателя и кампании в 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.1.0 # Контекст сборки — каталог с этим файлом. Если образа нет ни локально, ни в реестре, # достаточно `docker compose -f docker-compose.wsl.yml build`: доступ к Docker Hub # для запуска не обязателен. build: context: . args: VERSION: "1.1.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 при этом должен быть создан заранее и принадлежать вам).