You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Thanks for the project β the lazy NPP loader from #1371 is a nice improvement for CPU-only installs. While testing the resulting CUDA path on Windows we hit a regression for CUDA 13 environments, and I would like to report it (with a suggested fix) before sending a PR.
Summary
After PR #1371 ("Lazily load NPP libraries") landed, the Windows branch of NPPRuntimeLoader.cpp::_loadLibrary() hard-codes nppicc64_12.dll. On a CUDA 13 host (where nvidia-npp 13.x ships nppicc64_13.dll), loadNPPLibrary() always returns false and any CUDA device interface β both CudaDeviceInterface and BetaCudaDeviceInterface β fails with:
Failed to load NPP library. NPP is required for CUDA color conversion.
The Linux branch in the same function has a libnppicc.so.12 / libnppicc.so.13 fallback, but the Windows branch does not. This looks like an oversight rather than an intentional restriction.
Reproduction
Tested on:
Windows 11 (x64)
Visual Studio 2022 Build Tools 17.x (VCTools workload)
CUDA Toolkit 13.2
Python 3.13 in a uv-managed venv with nvidia-npp == 13.1.0.48 installed
torchcodec built from source on main (latest tested commit: 11a4d98a) with ENABLE_CUDA=1
importtorchimporttorchcodecfromtorchcodec.decodersimportVideoDecoderdec=VideoDecoder("test.mp4", device="cuda")
# RuntimeError: BetaCudaDeviceInterface, .../BetaCudaDeviceInterface.cpp:282,# Failed to load NPP library. NPP is required for CUDA color conversion.
The Windows-side nvidia-npp PyPI wheel places its DLLs at <venv>/Lib/site-packages/nvidia/cu13/bin/x86_64/, including:
nppc64_13.dll
nppicc64_13.dll <-- this is what NPPRuntimeLoader looks for, but with "_12" suffix
nppial64_13.dll
nppidei64_13.dll
... (no nppicc64_12.dll)
Adding the directory to os.add_dll_directory() and to PATH does not help: LoadLibrary("nppicc64_12.dll") simply has no matching file.
Root cause
src/torchcodec/_core/NPPRuntimeLoader.cpp, function _loadLibrary():
staticbool_loadLibrary() {
#if defined(WIN64) || defined(_WIN64)
#ifdef UNICODE
staticLPCWSTR nppiccDll = L"nppicc64_12.dll"; // <-- CUDA 12 hard-coded
#elsestaticLPCSTR nppiccDll = "nppicc64_12.dll";
#endif
g_nppicc_handle = LoadLibrary(nppiccDll);
if (g_nppicc_handle == nullptr) {
returnfalse;
}
#else// Linux already has the 12 / 13 fallback:
g_nppicc_handle = dlopen("libnppicc.so", RTLD_NOW);
if (g_nppicc_handle == nullptr) {
g_nppicc_handle = dlopen("libnppicc.so.12", RTLD_NOW);
}
if (g_nppicc_handle == nullptr) {
g_nppicc_handle = dlopen("libnppicc.so.13", RTLD_NOW);
}
if (g_nppicc_handle == nullptr) {
returnfalse;
}
#endifreturntrue;
}
Before PR #1371 the NPP library was statically linked via CMake (${CUDA_nppicc_LIBRARY}), so the NPP version matched the CUDA toolkit used at build time. After switching to runtime LoadLibrary, the Windows branch lost that flexibility because the filename now needs the matching version suffix.
Suggested fix
Mirror the Linux fallback on Windows: try nppicc64_13.dll first, fall back to nppicc64_12.dll. Trying 13 first is reasonable since older 12 setups can still match via the fallback path.
Verified on the reproduction environment above: with this patch applied and torchcodec rebuilt, VideoDecoder(..., device="cuda") initializes successfully and decoded frames flow through the CUDA color-conversion path.
I am happy to send a PR. Let me know whether you would like the fallback list extended (e.g. a future nppicc64_14.dll) or kept minimal to 13 / 12.
Why this matters
This is the only code path for CUDA color conversion on Windows + CUDA 13, since:
The torchcodec 0.12.0 Windows wheel on PyPI is CPU-only (0.12.0+cpu, built without ENABLE_CUDA).
The PyTorch wheel index (cu128 / cu130 / nightly) currently does not publish Windows CUDA wheels for torchcodec.
conda-forge's Windows + CUDA torchcodec is at 0.10.0, which predates PR Lazily load NPP librariesΒ #1371 and the 0.12-series streaming encoder.
So a Windows + CUDA 13 user must build torchcodec from source today, and this hard-coded DLL name blocks them at the first VideoDecoder(..., device="cuda") call.
Notes
nvidia-nvjpeg 13.x ships nvjpeg64_13.dll (same naming pattern). If torchcodec adds an equivalent runtime loader for nvJPEG in the future, the same multi-version logic would be worth keeping in mind.
Thanks for taking the time to read through this. Happy to provide additional logs, run experiments, or open a PR β whichever is most useful. Looking forward to your guidance.
Versions
Collecting environment information...
PyTorch version: 2.11.0+cu130
Is debug build: False
CUDA used to build PyTorch: 13.0
ROCM used to build PyTorch: N/A
OS: Microsoft Windows 11 Enterprise (10.0.26200 64 γγγ)
GCC version: Could not collect
Clang version: Could not collect
CMake version: version 4.3.2
Libc version: N/A
Python version: 3.13.9 (tags/v3.13.9:8183fa5, Oct 14 2025, 14:09:13) [MSC v.1944 64 bit (AMD64)] (64-bit runtime)
Python platform: Windows-11-10.0.26200-SP0
Is CUDA available: True
CUDA runtime version: 13.2.78
CUDA_MODULE_LOADING set to:
GPU models and configuration: GPU 0: NVIDIA GeForce RTX 5060 Ti
Nvidia driver version: 596.36
cuDNN version: Could not collect
Is XPU available: False
HIP runtime version: N/A
MIOpen runtime version: N/A
Is XNNPACK available: True
Caching allocator config: N/A
π Describe the bug
Hi torchcodec maintainers,
Thanks for the project β the lazy NPP loader from #1371 is a nice improvement for CPU-only installs. While testing the resulting CUDA path on Windows we hit a regression for CUDA 13 environments, and I would like to report it (with a suggested fix) before sending a PR.
Summary
After PR #1371 ("Lazily load NPP libraries") landed, the Windows branch of
NPPRuntimeLoader.cpp::_loadLibrary()hard-codesnppicc64_12.dll. On a CUDA 13 host (wherenvidia-npp 13.xshipsnppicc64_13.dll),loadNPPLibrary()always returnsfalseand any CUDA device interface β bothCudaDeviceInterfaceandBetaCudaDeviceInterfaceβ fails with:The Linux branch in the same function has a
libnppicc.so.12/libnppicc.so.13fallback, but the Windows branch does not. This looks like an oversight rather than an intentional restriction.Reproduction
Tested on:
nvidia-npp == 13.1.0.48installedmain(latest tested commit:11a4d98a) withENABLE_CUDA=1The Windows-side
nvidia-nppPyPI wheel places its DLLs at<venv>/Lib/site-packages/nvidia/cu13/bin/x86_64/, including:Adding the directory to
os.add_dll_directory()and toPATHdoes not help:LoadLibrary("nppicc64_12.dll")simply has no matching file.Root cause
src/torchcodec/_core/NPPRuntimeLoader.cpp, function_loadLibrary():Before PR #1371 the NPP library was statically linked via CMake (
${CUDA_nppicc_LIBRARY}), so the NPP version matched the CUDA toolkit used at build time. After switching to runtimeLoadLibrary, the Windows branch lost that flexibility because the filename now needs the matching version suffix.Suggested fix
Mirror the Linux fallback on Windows: try
nppicc64_13.dllfirst, fall back tonppicc64_12.dll. Trying 13 first is reasonable since older 12 setups can still match via the fallback path.static bool _loadLibrary() { #if defined(WIN64) || defined(_WIN64) #ifdef UNICODE - static LPCWSTR nppiccDll = L"nppicc64_12.dll"; + static const LPCWSTR nppiccDlls[] = { L"nppicc64_13.dll", L"nppicc64_12.dll" }; #else - static LPCSTR nppiccDll = "nppicc64_12.dll"; + static const LPCSTR nppiccDlls[] = { "nppicc64_13.dll", "nppicc64_12.dll" }; #endif - g_nppicc_handle = LoadLibrary(nppiccDll); + for (auto dll : nppiccDlls) { + g_nppicc_handle = LoadLibrary(dll); + if (g_nppicc_handle != nullptr) { + break; + } + } if (g_nppicc_handle == nullptr) { return false; } #elseVerified on the reproduction environment above: with this patch applied and torchcodec rebuilt,
VideoDecoder(..., device="cuda")initializes successfully and decoded frames flow through the CUDA color-conversion path.I am happy to send a PR. Let me know whether you would like the fallback list extended (e.g. a future
nppicc64_14.dll) or kept minimal to 13 / 12.Why this matters
This is the only code path for CUDA color conversion on Windows + CUDA 13, since:
0.12.0+cpu, built withoutENABLE_CUDA).cu128/cu130/ nightly) currently does not publish Windows CUDA wheels for torchcodec.So a Windows + CUDA 13 user must build torchcodec from source today, and this hard-coded DLL name blocks them at the first
VideoDecoder(..., device="cuda")call.Notes
nvidia-nvjpeg 13.xshipsnvjpeg64_13.dll(same naming pattern). If torchcodec adds an equivalent runtime loader for nvJPEG in the future, the same multi-version logic would be worth keeping in mind.Thanks for taking the time to read through this. Happy to provide additional logs, run experiments, or open a PR β whichever is most useful. Looking forward to your guidance.
Versions
Collecting environment information...
PyTorch version: 2.11.0+cu130
Is debug build: False
CUDA used to build PyTorch: 13.0
ROCM used to build PyTorch: N/A
OS: Microsoft Windows 11 Enterprise (10.0.26200 64 γγγ)
GCC version: Could not collect
Clang version: Could not collect
CMake version: version 4.3.2
Libc version: N/A
Python version: 3.13.9 (tags/v3.13.9:8183fa5, Oct 14 2025, 14:09:13) [MSC v.1944 64 bit (AMD64)] (64-bit runtime)
Python platform: Windows-11-10.0.26200-SP0
Is CUDA available: True
CUDA runtime version: 13.2.78
CUDA_MODULE_LOADING set to:
GPU models and configuration: GPU 0: NVIDIA GeForce RTX 5060 Ti
Nvidia driver version: 596.36
cuDNN version: Could not collect
Is XPU available: False
HIP runtime version: N/A
MIOpen runtime version: N/A
Is XNNPACK available: True
Caching allocator config: N/A
CPU:
Name: AMD Ryzen 7 9700X 8-Core Processor
Manufacturer: AuthenticAMD
Family: 107
Architecture: 9
ProcessorType: 3
DeviceID: CPU0
CurrentClockSpeed: 3800
MaxClockSpeed: 3800
L2CacheSize: 8192
L2CacheSpeed: None
Revision: 17408
Versions of relevant libraries:
[pip3] Could not collect
[conda] Could not collect
----- relevant packages (from uv pip list) -----
uv pip list | Select-String -Pattern "^(torch|nvidia|tensorrt|pytorch)"
nvidia-npp 13.1.0.48
nvidia-nvjpeg 13.1.0.48
nvidia-vfx 0.1.0.1
tensorrt 10.15.1.29
tensorrt-cu13 10.15.1.29
tensorrt-cu13-bindings 10.15.1.29
tensorrt-cu13-libs 10.15.1.29
torch 2.11.0+cu130
torch-tensorrt 2.11.0+cu130
torchcodec 0.13.0a0 F:\test\torchcodec
torchvision 0.26.0+cu130
----- torchcodec version -----
..venv\Scripts\python.exe -c "import torchcodec; print(torchcodec.version)"
0.13.0a0+11a4d98
----- FFmpeg version -----
& "$FFmpegRoot\bin\ffmpeg.exe" -version | Select-Object -First 1
ffmpeg version 8.1-full_build-www.gyan.dev Copyright (c) 2000-2026 the FFmpeg developers