Files
2026-07-13 13:35:51 +08:00

81 lines
2.8 KiB
Python

"""HugeCTR gpu_cache wrapper for graphbolt."""
from functools import reduce
from operator import mul
import torch
class GPUFeatureCache(object):
"""High-level wrapper for GPU embedding cache"""
def __init__(self, cache_shape, dtype):
major, _ = torch.cuda.get_device_capability()
assert (
major >= 7
), "GPUFeatureCache is supported only on CUDA compute capability >= 70 (Volta)."
self._cache = torch.ops.graphbolt.gpu_cache(cache_shape, dtype)
element_size = torch.tensor([], dtype=dtype).element_size()
self.max_size_in_bytes = reduce(mul, cache_shape) * element_size
self.total_miss = 0
self.total_queries = 0
def query(self, keys, async_op=False):
"""Queries the GPU cache.
Parameters
----------
keys : Tensor
The keys to query the GPU cache with.
async_op: bool
Boolean indicating whether the call is asynchronous. If so, the
result can be obtained by calling wait on the returned future.
Returns
-------
tuple(Tensor, Tensor, Tensor)
A tuple containing (values, missing_indices, missing_keys) where
values[missing_indices] corresponds to cache misses that should be
filled by quering another source with missing_keys.
"""
class _Waiter:
def __init__(self, gpu_cache, future):
self.gpu_cache = gpu_cache
self.future = future
def wait(self):
"""Returns the stored value when invoked."""
gpu_cache = self.gpu_cache
values, missing_index, missing_keys = (
self.future.wait() if async_op else self.future
)
# Ensure there is no leak.
self.gpu_cache = self.future = None
gpu_cache.total_queries += values.shape[0]
gpu_cache.total_miss += missing_keys.shape[0]
return values, missing_index, missing_keys
if async_op:
return _Waiter(self, self._cache.query_async(keys))
else:
return _Waiter(self, self._cache.query(keys)).wait()
def replace(self, keys, values):
"""Inserts key-value pairs into the GPU cache using the Least-Recently
Used (LRU) algorithm to remove old key-value pairs if it is full.
Parameters
----------
keys: Tensor
The keys to insert to the GPU cache.
values: Tensor
The values to insert to the GPU cache.
"""
self._cache.replace(keys, values)
@property
def miss_rate(self):
"""Returns the cache miss rate since creation."""
return self.total_miss / self.total_queries