173 lines
5.4 KiB
Python
173 lines
5.4 KiB
Python
import backend as F
|
|
|
|
import pytest
|
|
import torch
|
|
|
|
from dgl import graphbolt as gb
|
|
|
|
|
|
def _test_query_and_replace(policy1, policy2, keys, offset):
|
|
# Testing query_and_replace equivalence to query and then replace.
|
|
(
|
|
_,
|
|
index,
|
|
pointers,
|
|
missing_keys,
|
|
found_offsets,
|
|
missing_offsets,
|
|
) = policy1.query_and_replace(keys, offset)
|
|
found_cnt = keys.size(0) - missing_keys.size(0)
|
|
found_pointers = pointers[:found_cnt]
|
|
policy1.reading_completed(found_pointers, found_offsets)
|
|
missing_pointers = pointers[found_cnt:]
|
|
policy1.writing_completed(missing_pointers, missing_offsets)
|
|
|
|
(
|
|
_,
|
|
index2,
|
|
missing_keys2,
|
|
found_pointers2,
|
|
found_offsets2,
|
|
missing_offsets2,
|
|
) = policy2.query(keys + offset, 0)
|
|
policy2.reading_completed(found_pointers2, found_offsets2)
|
|
(_, missing_pointers2, missing_offsets2) = policy2.replace(
|
|
missing_keys2, missing_offsets2, 0
|
|
)
|
|
policy2.writing_completed(missing_pointers2, missing_offsets2)
|
|
|
|
assert torch.equal(index, index2)
|
|
assert torch.equal(missing_keys, missing_keys2 - offset)
|
|
|
|
|
|
@pytest.mark.parametrize("offsets", [False, True])
|
|
@pytest.mark.parametrize(
|
|
"dtype",
|
|
[
|
|
torch.bool,
|
|
torch.uint8,
|
|
torch.int8,
|
|
torch.int16,
|
|
torch.int32,
|
|
torch.int64,
|
|
torch.float16,
|
|
torch.bfloat16,
|
|
torch.float32,
|
|
torch.float64,
|
|
],
|
|
)
|
|
@pytest.mark.parametrize("feature_size", [2, 16])
|
|
@pytest.mark.parametrize("num_parts", [1, 2, None])
|
|
@pytest.mark.parametrize("policy", ["s3-fifo", "sieve", "lru", "clock"])
|
|
@pytest.mark.parametrize("offset", [0, 1111111])
|
|
def test_feature_cache(offsets, dtype, feature_size, num_parts, policy, offset):
|
|
cache_size = 32 * (
|
|
torch.get_num_threads() if num_parts is None else num_parts
|
|
)
|
|
a = torch.randint(0, 2, [1024, feature_size], dtype=dtype)
|
|
cache = gb.impl.CPUFeatureCache(
|
|
(cache_size,) + a.shape[1:], a.dtype, policy, num_parts
|
|
)
|
|
cache2 = gb.impl.CPUFeatureCache(
|
|
(cache_size,) + a.shape[1:], a.dtype, policy, num_parts
|
|
)
|
|
policy1 = gb.impl.CPUFeatureCache(
|
|
(cache_size,) + a.shape[1:], a.dtype, policy, num_parts
|
|
)._policy
|
|
policy2 = gb.impl.CPUFeatureCache(
|
|
(cache_size,) + a.shape[1:], a.dtype, policy, num_parts
|
|
)._policy
|
|
reader_fn = lambda keys: a[keys]
|
|
|
|
keys = torch.tensor([0, 1])
|
|
values, missing_index, missing_keys, missing_offsets = cache.query(
|
|
keys, offset
|
|
)
|
|
if not offsets:
|
|
missing_offsets = None
|
|
assert torch.equal(
|
|
missing_keys.flip([0]) if num_parts == 1 else missing_keys.sort()[0],
|
|
keys,
|
|
)
|
|
|
|
missing_values = a[missing_keys]
|
|
cache.replace(missing_keys, missing_values, missing_offsets, offset)
|
|
values[missing_index] = missing_values
|
|
assert torch.equal(values, a[keys])
|
|
assert torch.equal(
|
|
cache2.query_and_replace(keys, reader_fn, offset), a[keys]
|
|
)
|
|
|
|
_test_query_and_replace(policy1, policy2, keys, offset)
|
|
|
|
pin_memory = F._default_context_str == "gpu"
|
|
|
|
keys = torch.arange(1, 33, pin_memory=pin_memory)
|
|
values, missing_index, missing_keys, missing_offsets = cache.query(
|
|
keys, offset
|
|
)
|
|
if not offsets:
|
|
missing_offsets = None
|
|
assert torch.equal(
|
|
missing_keys.flip([0]) if num_parts == 1 else missing_keys.sort()[0],
|
|
torch.arange(2, 33),
|
|
)
|
|
assert not pin_memory or values.is_pinned()
|
|
|
|
missing_values = a[missing_keys]
|
|
cache.replace(missing_keys, missing_values, missing_offsets, offset)
|
|
values[missing_index] = missing_values
|
|
assert torch.equal(values, a[keys])
|
|
assert torch.equal(
|
|
cache2.query_and_replace(keys, reader_fn, offset), a[keys]
|
|
)
|
|
|
|
_test_query_and_replace(policy1, policy2, keys, offset)
|
|
|
|
values, missing_index, missing_keys, missing_offsets = cache.query(
|
|
keys, offset
|
|
)
|
|
if not offsets:
|
|
missing_offsets = None
|
|
assert torch.equal(missing_keys.flip([0]), torch.tensor([]))
|
|
|
|
missing_values = a[missing_keys]
|
|
cache.replace(missing_keys, missing_values, missing_offsets, offset)
|
|
values[missing_index] = missing_values
|
|
assert torch.equal(values, a[keys])
|
|
assert torch.equal(
|
|
cache2.query_and_replace(keys, reader_fn, offset), a[keys]
|
|
)
|
|
|
|
_test_query_and_replace(policy1, policy2, keys, offset)
|
|
|
|
values, missing_index, missing_keys, missing_offsets = cache.query(
|
|
keys, offset
|
|
)
|
|
if not offsets:
|
|
missing_offsets = None
|
|
assert torch.equal(missing_keys.flip([0]), torch.tensor([]))
|
|
|
|
missing_values = a[missing_keys]
|
|
cache.replace(missing_keys, missing_values, missing_offsets, offset)
|
|
values[missing_index] = missing_values
|
|
assert torch.equal(values, a[keys])
|
|
assert torch.equal(
|
|
cache2.query_and_replace(keys, reader_fn, offset), a[keys]
|
|
)
|
|
|
|
_test_query_and_replace(policy1, policy2, keys, offset)
|
|
|
|
assert cache.miss_rate == cache2.miss_rate
|
|
|
|
raw_feature_cache = torch.ops.graphbolt.feature_cache(
|
|
(cache_size,) + a.shape[1:], a.dtype, pin_memory
|
|
)
|
|
idx = torch.tensor([0, 1, 2])
|
|
raw_feature_cache.replace(idx, a[idx])
|
|
val = raw_feature_cache.index_select(idx)
|
|
assert torch.equal(val, a[idx])
|
|
if pin_memory:
|
|
val = raw_feature_cache.index_select(idx.to(F.ctx()))
|
|
assert torch.equal(val, a[idx].to(F.ctx()))
|