()
| 331 | torch is None or not torch.cuda.is_available(), reason="Requires torch and CUDA" |
| 332 | ) |
| 333 | def test_cuda_memory_alloc_noleak() -> None: |
| 334 | assert torch is not None |
| 335 | mod = tvm_ffi.cpp.load_inline( |
| 336 | name="hello", |
| 337 | cuda_sources=r""" |
| 338 | #include <tvm/ffi/function.h> |
| 339 | #include <tvm/ffi/container/tensor.h> |
| 340 | |
| 341 | namespace ffi = tvm::ffi; |
| 342 | |
| 343 | ffi::Tensor return_tensor(tvm::ffi::TensorView x) { |
| 344 | ffi::Tensor y = ffi::Tensor::FromEnvAlloc( |
| 345 | TVMFFIEnvTensorAlloc, x.shape(), x.dtype(), x.device()); |
| 346 | return y; |
| 347 | } |
| 348 | """, |
| 349 | functions=["return_tensor"], |
| 350 | ) |
| 351 | |
| 352 | def run_check() -> None: |
| 353 | """Must run in a separate function to ensure deletion happens before mod unloads.""" |
| 354 | assert torch is not None |
| 355 | x = torch.arange(1024 * 1024, dtype=torch.float32, device="cuda") |
| 356 | current_allocated = torch.cuda.memory_allocated() |
| 357 | repeat = 8 |
| 358 | for i in range(repeat): |
| 359 | mod.return_tensor(x) |
| 360 | diff = torch.cuda.memory_allocated() - current_allocated |
| 361 | # memory should not grow as we loop over |
| 362 | assert diff <= 1024**2 * 8 |
| 363 | |
| 364 | run_check() |
nothing calls this directly
no test coverage detected