Files
local-transcriber/docs/adr/001-cuda-bootstrap.md
T

11 KiB
Raw Blame History

ADR-001: Необязательная CUDA и загрузка cuBLAS из окружения

Статус: Принято; пересмотр обязательной cuBLAS от 2026-03-18 Дата: 2026-03-18 Обновлено: 2026-09-21, задача #2

Контекст

CTranslate2 загружает cuBLAS динамически и не поставляет её в своём wheel. Прежняя обязательная зависимость добавляла около 581 MB скачивания на Linux x86_64, даже если пользователь работал только через ONNX CPU. Наличие nvidia-smi доказывает наличие утилиты драйвера, но не совместимость GPU с runtime. Автоматический выбор CUDA мог приводить к ошибке на старом GPU.

Прежнее утверждение о недоступности Windows wheel nvidia-cublas-cu12 было ошибочным: такой wheel есть и для закреплённой версии 12.9.1.4. Следовательно, системный CUDA Toolkit не должен быть обязательным способом подключения Windows.

Решение

CUDA подключается через extra cuda на Linux/WSL x86_64 и Windows x64. Драйвер NVIDIA остаётся внешним требованием; Windows также требует Visual C++ Runtime x64. Установка extra не включает CUDA: пользователь выбирает её через CLI или TOML. auto всегда выбирает ONNX CPU, ASR и VAD получают явный CPUExecutionProvider. Команды установки и обновления — в README.

CTranslate2 4.8.1 и cuBLAS 12.9.1.4 закреплены в pyproject.toml, чтобы установка через uv tool и из клона использовала проверенное сочетание. В cuBLAS 12.9.2.10 появилась дополнительная зависимость NVRTC. Обновление версий требует повторной проверки библиотек и bootstrap; одного обновления lock-файла недостаточно.

Linux: preload по полному пути

_cuda_bootstrap.py загружает libcublas.so.12 через ctypes.CDLL с RTLD_GLOBAL. Линкер затем разрешает запрос CTranslate2 по soname. Изменение LD_LIBRARY_PATH внутри процесса не решает задачу: glibc кеширует пути поиска. Путь optional-пакета определяется через nvidia.cublas.__path__, что поддерживает namespace package без __file__.

Windows: регистрация каталога и preload DLL

Bootstrap регистрирует nvidia/cublas/bin через os.add_dll_directory, затем загружает по абсолютным путям сначала cublasLt64_12.dll, затем cublas64_12.dll. Handles библиотек и регистрации каталога хранятся до завершения процесса. Повторный вызов не загружает их заново. Это обеспечивает доступность уже загруженных DLL для динамического загрузчика CTranslate2 и не требует изменения системного PATH.

Bootstrap вызывается только при создании CUDA-модели, до локального импорта WhisperModel. Если CTranslate2 ранее импортирован для декодирования аудио, preload всё равно выполняется до создания CUDA-модели. CPU-путь bootstrap не вызывает. Отсутствие optional-пакета безопасно: системная cuBLAS всё ещё может обслужить явно выбранную CUDA. Ошибка загрузки найденной Windows DLL сохраняется.

Ошибки и явный выбор

Явный device из CLI или TOML передаёт strict_device=True при загрузке и транскрипции. CUDA не заменяется молча на CPU. Подсказки различают отсутствие библиотек, проблемы драйвера, несовместимость GPU/runtime и нехватку памяти; отказ по неподдерживаемому типу вычислений учитывает устройство, чтобы одинаковая ошибка CTranslate2 на CPU не получала CUDA-подсказку. Исходное сообщение сохраняется. Неизвестная ошибка не получает произвольный совет установить Toolkit. Это одинаково для одного файла и батча.

Прежний механизм fallback оркестратора при strict_device=False сохранён для существующих программных callers. Автоматический CLI-путь теперь ONNX, поэтому он не попадает в CUDA fallback.

Проверка зависимостей Windows

Статическая проверка 2026-09-21: скачаны wheels из PyPI, проверены SHA-256, для DLL/PYD прочитаны PE imports через objdump -p и строки динамической загрузки. Модели распознавания не скачивались.

  • ctranslate2-4.8.1-cp313-cp313-win_amd64.whl, SHA-256 d52499f05a60a791aeadee28d609efa130142f376d1ea76b2b1c593bb01f8827. ctranslate2.dll содержит имена cublas64_12.dll и nvcuda.dll; ссылок на cuDNN и динамическую cudart в этой DLL не обнаружено. В wheel есть cudnn64_9.dll, но её наличие не означает использование cuDNN проверенной рабочей DLL. OpenMP DLL поставляется внутри wheel; импорты MSVCP/VCRUNTIME требуют Visual C++ Runtime.
  • nvidia_cublas_cu12-12.9.1.4-py3-none-win_amd64.whl, SHA-256 1e5fee10662e6e52bd71dec533fbbd4971bb70a5f24f3bc3793e5c2e9dc640bf. DLL находятся в nvidia/cublas/bin. cuBLAS импортирует cuBLAS Lt и KERNEL32; cuBLAS Lt импортирует KERNEL32. В строках cuBLAS Lt также найдена динамическая ссылка на nvrtc64_120_0.dll, которой нет в PE imports. Обязательность NVRTC для Whisper этим статическим анализом не установлена; первый реальный Windows-прогон должен проверить и этот путь загрузки. nvblas64_12.dll не требуется проверенному пути CTranslate2.

Основания: CTranslate2 4.8.1 на PyPI, cuBLAS 12.9.1.4 на PyPI, загрузчик CTranslate2, метаданные cuBLAS 12.9.2.10.

Это обоснование состава extra для конкретных wheels, а не подтверждение транскрипции на Windows GPU. Реальный прогон Windows x64 с драйвером и extra, без Toolkit и ручной правки PATH, не выполнен. Linux-тесты с подменой Windows API не заменяют такую проверку.

Проверка поставки и поведения

На Linux выполнены uv run pytest: 524 passed, 2 skipped. Пропуски — Windows-only кодировка OEM и интеграционный bootstrap без optional-пакета. До удаления cuBLAS интеграционный тест Linux bootstrap проходил. Обычный uv sync --locked удаляет прежнюю обязательную cuBLAS; uv sync --extra cuda --locked --dry-run возвращает её в план установки.

Метаданные собранного wheel проверены для 12 сочетаний платформы, архитектуры и extra. Полное разрешение зависимостей wheel через uv pip compile для Linux и Windows, с extra и без, подтверждает отсутствие NVIDIA-пакетов в обычной установке и наличие только cuBLAS 12.9.1.4 при выборе extra.

Формы uv tool install для клона, клона с extra и именованной Git-зависимости с extra проверены в отдельном временном каталоге tools. Для проверки самой команды зависимости были исключены; их разрешение проверено отдельно выше. Git-транспорт проверялся через локальный репозиторий и ветку реализации, а не через ещё не опубликованную ветку на сервере. Версия uv — 0.12.17.

Последствия и альтернативы

  • Обычная установка не требует NVIDIA-пакетов. FasterWhisper CPU сохраняется.
  • Дополнительные библиотеки скачиваются только по выбору пользователя.
  • Единый extra заменяет требование установить полный Toolkit на Windows; существующая системная установка библиотек остаётся допустимой.
  • Отклонено сохранение обязательной cuBLAS ради готовности CUDA сразу после установки: это увеличивает CPU-установку и не решает несовместимость GPU.
  • Отклонено автоматическое включение CUDA по драйверу или extra: установка библиотек не должна менять движок и модель по умолчанию.
  • Перезапуск процесса с LD_LIBRARY_PATH не нужен; явная загрузка библиотек решает проблему без изменения обработки сигналов и файловых дескрипторов.
  • CUDA extra на Windows ARM64, Linux ARM и macOS в эту задачу не входит.