Repository navigation
Description
A program lowered with CudaPartitioner runs correctly when CUDA device 0 is the current device. When the caller makes device 1 current first (torch.cuda.set_device(1)), execute() fails with an illegal memory access. The delegate seems to use device 0 no matter which device is current.
On a machine with several GPUs, this means a program can only run on the first GPU. The only workaround I found is to pick the GPU with CUDA_VISIBLE_DEVICES, so that the wanted GPU becomes device 0.
Repro
Needs 2 GPUs. It exports a small model once, then runs it in a fresh process with device 0 current and then with device 1 current.
import os, subprocess, sys, tempfile
import torch
from executorch.backends.cuda.cuda_backend import CudaBackend
from executorch.backends.cuda.cuda_partitioner import CudaPartitioner
from executorch.exir import to_edge_transform_and_lower
from executorch.runtime import Runtime
def make_model():
torch.manual_seed(0)
return torch.nn.Sequential(torch.nn.Linear(8, 16), torch.nn.ELU(), torch.nn.Linear(16, 4)).eval()
if len(sys.argv) == 1:
folder = tempfile.mkdtemp()
program = to_edge_transform_and_lower(
torch.export.export(make_model(), (torch.zeros(1, 8),)),
partitioner=[CudaPartitioner([CudaBackend.generate_method_name_compile_spec("forward")])],
).to_executorch()
with open(os.path.join(folder, "model.pte"), "wb") as f:
program.write_to_file(f)
program.write_tensor_data_to_file(folder)
# Run each case in a fresh process, because a failed run leaves the CUDA context broken.
for device in ("0", "1"):
subprocess.run([sys.executable, __file__, folder, device])
else:
folder, device = sys.argv[1], int(sys.argv[2])
torch.cuda.set_device(device)
method = Runtime.get().load_program(
os.path.join(folder, "model.pte"), data_path=os.path.join(folder, "aoti_cuda_blob.ptd")
).load_method("forward")
x = torch.randn(1, 8)
try:
out = method.execute([x])[0]
print(f"current device {device}: OK, max error {(out - make_model()(x)).abs().max().item():.1e}")
except RuntimeError as e:
print(f"current device {device}: FAILED: {e}")Output:
current device 0: OK, max error 4.5e-08
[cuda_allocator.cpp:700] cudaFreeAsync failed: an illegal memory access was encountered (ptr=0x402000200, device -1)
Error: CUDA driver error: an illegal memory access was encountered
[cuda_backend.cpp:1202] AOTInductorModelContainerRun failed with error code 1
current device 1: FAILED: method->execute() failed with error 0x1: cudaFreeAsync failed: an illegal memory access was encountered (ptr=0x402000200, device -1); ... AOTInductorModelContainerRun failed with error code 1; CALL_DELEGATE execute failed at instruction 1: 0x1
Expected
The program runs on the current device, or the caller can choose the device when loading the program. If only device 0 is supported, a clear error at load time would help more than a crash.
Environment
- ExecuTorch 1.6.0+cu132, PyTorch 2.15.0+cu132, Python 3.12
- 2x NVIDIA A100 80GB, driver 580.126.09, CUDA toolkit 12.8 for the export
- Linux x86_64
Activity