from __future__ import annotations
import ctypes
from contextlib import contextmanager
from pathlib import Path
from typing import Iterator
try:
ctypes.CDLL("libcudart.so", mode=ctypes.RTLD_GLOBAL)
except OSError:
pass
import torch from torch.utils.cpp_extension import load_inline
_SOURCE = r"""
extern "C" {
void* mx_classic_alloc(ptrdiff_t size, int device, void* stream) {
(void) stream;
int prev = -1;
cudaGetDevice(&prev);
cudaSetDevice(device);
void* ptr = nullptr;
cudaError_t err = cudaMalloc(&ptr, (size_t) size);
if (prev >= 0) cudaSetDevice(prev);
if (err != cudaSuccess) return nullptr;
return ptr;
}
void mx_classic_free(void* ptr, ptrdiff_t size, int device, void* stream) {
(void) size; (void) stream;
int prev = -1;
cudaGetDevice(&prev);
cudaSetDevice(device);
cudaFree(ptr);
if (prev >= 0) cudaSetDevice(prev);
}
}
"""
_pool: "torch.cuda.MemPool | None" = None
_allocator_wrapper: "torch.cuda.memory.CUDAPluggableAllocator | None" = None
def _get_pool() -> "torch.cuda.MemPool":
global _pool, _allocator_wrapper
if _pool is not None:
return _pool
module = load_inline(
name="mx_classic_cuda_alloc",
cpp_sources=[_SOURCE],
functions=[],
extra_cflags=["-O2"],
with_cuda=True,
)
so_path = Path(module.__file__)
_allocator_wrapper = torch.cuda.memory.CUDAPluggableAllocator(
str(so_path), "mx_classic_alloc", "mx_classic_free"
)
_pool = torch.cuda.MemPool(_allocator_wrapper.allocator())
return _pool
@contextmanager
def classic_cuda_alloc() -> Iterator[None]:
pool = _get_pool()
with torch.cuda.use_mem_pool(pool):
yield