"""Module for dynamo precompile context tests."""
import unittest
import torch
import torch_npu
import torch_npu._inductor
import torch._dynamo
import torch._dynamo.test_case
import torch._functorch
from torch._dynamo.precompile_context import BackendCacheArtifact, PrecompileContext
from torch._functorch import config as functorch_config
from torch._functorch._aot_autograd.autograd_cache import (
BundledAOTAutogradCacheArtifact,
)
from torch._inductor.test_case import TestCase as InductorTestCase
from torch.testing._internal.inductor_utils import requires_triton
DEVICE = "npu"
@functorch_config.patch({"enable_autograd_cache": True})
@torch._dynamo.config.patch(
{"caching_precompile": True}
)
class PrecompileContextTests(InductorTestCase):
def setUp(self):
"""
Reset all counters and caches before each unit test
"""
super().setUp()
PrecompileContext.clear()
@staticmethod
def _check_device():
if not torch.npu.is_available():
raise unittest.SkipTest("Requires NPU")
@requires_triton()
def test_basic(self):
"""
Test that after torch.compile, PrecompileContext._new_cache_artifacts length is 1
"""
self._check_device()
def simple_function(x):
return x.sin() + x.cos()
compiled_fn = torch.compile(simple_function)
x = torch.randn(10, device=DEVICE, requires_grad=True)
result = compiled_fn(x)
result.sum().backward()
self.assertEqual(len(PrecompileContext._dynamo_cache_entries), 1)
self.assertEqual(len(PrecompileContext._backend_artifacts_by_key), 1)
cache_entries, _ = PrecompileContext.create_cache_entries()
self.assertEqual(len(cache_entries), 1)
@requires_triton()
def test_serialize_by_key(self):
self._check_device()
def simple_function(x):
return x.sin() + x.cos()
compiled_fn = torch.compile(simple_function)
x = torch.randn(10, device=DEVICE, requires_grad=True)
result = compiled_fn(x)
result.sum().backward()
self.assertEqual(len(PrecompileContext._dynamo_cache_entries), 1)
self.assertEqual(len(PrecompileContext._backend_artifacts_by_key), 1)
for key in PrecompileContext._backend_artifacts_by_key:
result = PrecompileContext.serialize_artifact_by_key(key)
self.assertEqual(isinstance(result, BackendCacheArtifact), True)
self.assertEqual(result.key, key)
result, _ = PrecompileContext.create_cache_entries()
self.assertEqual(len(result), 1)
@requires_triton()
def test_editable(self):
"""
Test that after torch.compile, PrecompileContext._new_cache_artifacts length is 1
"""
self._check_device()
def simple_function(x):
return x.sin() + x.cos()
compiled_fn = torch.compile(simple_function)
x = torch.randn(10, device=DEVICE, requires_grad=True)
result = compiled_fn(x)
result.sum().backward()
self.assertEqual(len(PrecompileContext._dynamo_cache_entries), 1)
self.assertEqual(len(PrecompileContext._backend_artifacts_by_key), 1)
key = next(iter(PrecompileContext._backend_artifacts_by_key))
def edit_fn(x):
x._my_private_field = 42
return x
PrecompileContext.edit_artifact(key, edit_fn)
result = PrecompileContext.serialize_artifact_by_key(key)
self.assertEqual(isinstance(result, BundledAOTAutogradCacheArtifact), True)
self.assertEqual(result.key, key)
result, _ = PrecompileContext.create_cache_entries()
self.assertEqual(len(result), 1)
aot_autograd_artifacts = next(iter(result.values())).backends
self.assertEqual(len(aot_autograd_artifacts), 1)
entry = next(iter(aot_autograd_artifacts.values())).content
self.assertEqual(entry._my_private_field, 42)
if __name__ == "__main__":
from torch._dynamo.test_case import run_tests
run_tests()