# ADR-001: Необязательная CUDA и загрузка cuBLAS из окружения **Статус**: Принято; пересмотр обязательной cuBLAS от 2026-03-18 **Дата**: 2026-03-18 **Обновлено**: 2026-09-21, задача [#2](https://git.dementev.space/ddmitry/local-transcriber/issues/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](../../README.md#подключение-cuda). 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](https://pypi.org/project/ctranslate2/4.8.1/#files), [cuBLAS 12.9.1.4 на PyPI](https://pypi.org/project/nvidia-cublas-cu12/12.9.1.4/#files), [загрузчик CTranslate2](https://github.com/OpenNMT/CTranslate2/blob/v4.8.1/python/ctranslate2/__init__.py), [метаданные cuBLAS 12.9.2.10](https://pypi.org/pypi/nvidia-cublas-cu12/12.9.2.10/json). Это обоснование состава 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 в эту задачу не входит.