Skip to content

Commit

Permalink
refactor: Rigging python tests in pytest for CI and Nox
Browse files Browse the repository at this point in the history
Signed-off-by: Naren Dasan <[email protected]>
  • Loading branch information
narendasan committed Jul 22, 2022
1 parent 5ad9826 commit 2be072a
Show file tree
Hide file tree
Showing 19 changed files with 844 additions and 838 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,6 @@ bazel-Torch-TensorRT-Preview
docsrc/src/
bazel-TensorRT
bazel-tensorrt
.pytest_cache
*.cache
*cifar-10-batches-py*
5 changes: 4 additions & 1 deletion examples/int8/training/vgg16/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
torch>=1.10.0
tensorboard>=1.14.0
pytorch-quantization --extra-index-url https://pypi.ngc.nvidia.com
nvidia-pyindex
--extra-index-url https://pypi.ngc.nvidia.com
pytorch-quantization>=2.1.2
tqdm
50 changes: 32 additions & 18 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@

# Use system installed Python packages
PYT_PATH='/opt/conda/lib/python3.8/site-packages' if not 'PYT_PATH' in os.environ else os.environ["PYT_PATH"]
print(f"Using python path {PYT_PATH}")

# Set the root directory to the directory of the noxfile unless the user wants to
# TOP_DIR
TOP_DIR=os.path.dirname(os.path.realpath(__file__)) if not 'TOP_DIR' in os.environ else os.environ["TOP_DIR"]
print(f"Test root directory {TOP_DIR}")

# Set the USE_CXX11=1 to use cxx11_abi
USE_CXX11=0 if not 'USE_CXX11' in os.environ else os.environ["USE_CXX11"]
if USE_CXX11:
print("Using cxx11 abi")

# Set the USE_HOST_DEPS=1 to use host dependencies for tests
USE_HOST_DEPS=0 if not 'USE_HOST_DEPS' in os.environ else os.environ["USE_HOST_DEPS"]
if USE_HOST_DEPS:
print("Using dependencies from host python")

SUPPORTED_PYTHON_VERSIONS=["3.7", "3.8", "3.9", "3.10"]

Expand Down Expand Up @@ -58,6 +64,12 @@ def download_datasets(session):

def train_model(session):
session.chdir(os.path.join(TOP_DIR, 'examples/int8/training/vgg16'))
session.install("-r", "requirements.txt")
if os.path.exists('vgg16_ckpts/ckpt_epoch25.pth'):
session.run_always('python',
'export_ckpt.py',
'vgg16_ckpts/ckpt_epoch25.pth')
return
if USE_HOST_DEPS:
session.run_always('python',
'main.py',
Expand Down Expand Up @@ -140,14 +152,14 @@ def run_base_tests(session):
print("Running basic tests")
session.chdir(os.path.join(TOP_DIR, 'tests/py'))
tests = [
"test_api.py",
"test_to_backend_api.py",
"api",
"integrations/test_to_backend_api.py",
]
for test in tests:
if USE_HOST_DEPS:
session.run_always('python', test, env={'PYTHONPATH': PYT_PATH})
session.run_always('pytest', test, env={'PYTHONPATH': PYT_PATH})
else:
session.run_always("python", test)
session.run_always("pytest", test)

def run_accuracy_tests(session):
print("Running accuracy tests")
Expand All @@ -169,23 +181,23 @@ def copy_model(session):
session.run_always('cp',
'-rpf',
os.path.join(TOP_DIR, src_file),
os.path.join(TOP_DIR, str('tests/py/') + file_name),
os.path.join(TOP_DIR, str('tests/modules/') + file_name),
external=True)

def run_int8_accuracy_tests(session):
print("Running accuracy tests")
copy_model(session)
session.chdir(os.path.join(TOP_DIR, 'tests/py'))
tests = [
"test_ptq_dataloader_calibrator.py",
"test_ptq_to_backend.py",
"test_qat_trt_accuracy.py",
"ptq/test_ptq_to_backend.py",
"ptq/test_ptq_dataloader_calibrator.py",
"qat/",
]
for test in tests:
if USE_HOST_DEPS:
session.run_always('python', test, env={'PYTHONPATH': PYT_PATH})
session.run_always('pytest', test, env={'PYTHONPATH': PYT_PATH})
else:
session.run_always("python", test)
session.run_always("pytest", test)

def run_trt_compatibility_tests(session):
print("Running TensorRT compatibility tests")
Expand All @@ -197,9 +209,9 @@ def run_trt_compatibility_tests(session):
]
for test in tests:
if USE_HOST_DEPS:
session.run_always('python', test, env={'PYTHONPATH': PYT_PATH})
session.run_always('pytest', test, env={'PYTHONPATH': PYT_PATH})
else:
session.run_always("python", test)
session.run_always("pytest", test)

def run_dla_tests(session):
print("Running DLA tests")
Expand All @@ -209,9 +221,9 @@ def run_dla_tests(session):
]
for test in tests:
if USE_HOST_DEPS:
session.run_always('python', test, env={'PYTHONPATH': PYT_PATH})
session.run_always('pytest', test, env={'PYTHONPATH': PYT_PATH})
else:
session.run_always("python", test)
session.run_always("pytest", test)

def run_multi_gpu_tests(session):
print("Running multi GPU tests")
Expand All @@ -221,9 +233,9 @@ def run_multi_gpu_tests(session):
]
for test in tests:
if USE_HOST_DEPS:
session.run_always('python', test, env={'PYTHONPATH': PYT_PATH})
session.run_always('pytest', test, env={'PYTHONPATH': PYT_PATH})
else:
session.run_always("python", test)
session.run_always("pytest", test)

def run_l0_api_tests(session):
if not USE_HOST_DEPS:
Expand All @@ -245,7 +257,6 @@ def run_l1_accuracy_tests(session):
if not USE_HOST_DEPS:
install_deps(session)
install_torch_trt(session)
download_models(session)
download_datasets(session)
train_model(session)
run_accuracy_tests(session)
Expand All @@ -255,7 +266,6 @@ def run_l1_int8_accuracy_tests(session):
if not USE_HOST_DEPS:
install_deps(session)
install_torch_trt(session)
download_models(session)
download_datasets(session)
train_model(session)
finetune_model(session)
Expand Down Expand Up @@ -313,4 +323,8 @@ def l2_multi_gpu_tests(session):
@nox.session(python=SUPPORTED_PYTHON_VERSIONS, reuse_venv=True)
def download_test_models(session):
"""Grab all the models needed for testing"""
try:
import torch
except ModuleNotFoundError:
install_deps(session)
download_models(session)
4 changes: 2 additions & 2 deletions tests/modules/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"model": timm.create_model('vit_base_patch16_224', pretrained=True),
"path": "script"
},
"pool": {
"pooling": {
"model": cm.Pool(),
"path": "trace"
},
Expand All @@ -104,7 +104,7 @@
"model": cm.FallbackInplaceOPIf(),
"path": "script"
},
"bert-base-uncased": {
"bert_base_uncased": {
"model": cm.BertModule(),
"path": "trace"
}
Expand Down
2 changes: 0 additions & 2 deletions tests/modules/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
-f https://download.pytorch.org/whl/torch_stable.html
#torch==1.11.0+cu113
timm==v0.4.12
transformers==4.17.0
190 changes: 190 additions & 0 deletions tests/py/api/test_classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import unittest
import torch_tensorrt as torchtrt
import torch
import torchvision.models as models
import copy
from typing import Dict

class TestDevice(unittest.TestCase):

def test_from_string_constructor(self):
device = torchtrt.Device("cuda:0")
self.assertEqual(device.device_type, torchtrt.DeviceType.GPU)
self.assertEqual(device.gpu_id, 0)

device = torchtrt.Device("gpu:1")
self.assertEqual(device.device_type, torchtrt.DeviceType.GPU)
self.assertEqual(device.gpu_id, 1)

def test_from_string_constructor_dla(self):
device = torchtrt.Device("dla:0")
self.assertEqual(device.device_type, torchtrt.DeviceType.DLA)
self.assertEqual(device.gpu_id, 0)
self.assertEqual(device.dla_core, 0)

device = torchtrt.Device("dla:1", allow_gpu_fallback=True)
self.assertEqual(device.device_type, torchtrt.DeviceType.DLA)
self.assertEqual(device.gpu_id, 0)
self.assertEqual(device.dla_core, 1)
self.assertEqual(device.allow_gpu_fallback, True)

def test_kwargs_gpu(self):
device = torchtrt.Device(gpu_id=0)
self.assertEqual(device.device_type, torchtrt.DeviceType.GPU)
self.assertEqual(device.gpu_id, 0)

def test_kwargs_dla_and_settings(self):
device = torchtrt.Device(dla_core=1, allow_gpu_fallback=False)
self.assertEqual(device.device_type, torchtrt.DeviceType.DLA)
self.assertEqual(device.gpu_id, 0)
self.assertEqual(device.dla_core, 1)
self.assertEqual(device.allow_gpu_fallback, False)

device = torchtrt.Device(gpu_id=1, dla_core=0, allow_gpu_fallback=True)
self.assertEqual(device.device_type, torchtrt.DeviceType.DLA)
self.assertEqual(device.gpu_id, 1)
self.assertEqual(device.dla_core, 0)
self.assertEqual(device.allow_gpu_fallback, True)

def test_from_torch(self):
device = torchtrt.Device._from_torch_device(torch.device("cuda:0"))
self.assertEqual(device.device_type, torchtrt.DeviceType.GPU)
self.assertEqual(device.gpu_id, 0)


class TestInput(unittest.TestCase):

def _verify_correctness(self, struct: torchtrt.Input, target: Dict) -> bool:
internal = struct._to_internal()

list_eq = lambda al, bl: all([a == b for (a, b) in zip(al, bl)])

eq = lambda a, b: a == b

def field_is_correct(field, equal_fn, a1, a2):
equal = equal_fn(a1, a2)
if not equal:
print("\nField {} is incorrect: {} != {}".format(field, a1, a2))
return equal

min_ = field_is_correct("min", list_eq, internal.min, target["min"])
opt_ = field_is_correct("opt", list_eq, internal.opt, target["opt"])
max_ = field_is_correct("max", list_eq, internal.max, target["max"])
is_dynamic_ = field_is_correct("is_dynamic", eq, internal.input_is_dynamic, target["input_is_dynamic"])
explicit_set_dtype_ = field_is_correct("explicit_dtype", eq, internal._explicit_set_dtype,
target["explicit_set_dtype"])
dtype_ = field_is_correct("dtype", eq, int(internal.dtype), int(target["dtype"]))
format_ = field_is_correct("format", eq, int(internal.format), int(target["format"]))

return all([min_, opt_, max_, is_dynamic_, explicit_set_dtype_, dtype_, format_])

def test_infer_from_example_tensor(self):
shape = [1, 3, 255, 255]
target = {
"min": shape,
"opt": shape,
"max": shape,
"input_is_dynamic": False,
"dtype": torchtrt.dtype.half,
"format": torchtrt.TensorFormat.contiguous,
"explicit_set_dtype": True
}

example_tensor = torch.randn(shape).half()
i = torchtrt.Input._from_tensor(example_tensor)
self.assertTrue(self._verify_correctness(i, target))

def test_static_shape(self):
shape = [1, 3, 255, 255]
target = {
"min": shape,
"opt": shape,
"max": shape,
"input_is_dynamic": False,
"dtype": torchtrt.dtype.unknown,
"format": torchtrt.TensorFormat.contiguous,
"explicit_set_dtype": False
}

i = torchtrt.Input(shape)
self.assertTrue(self._verify_correctness(i, target))

i = torchtrt.Input(tuple(shape))
self.assertTrue(self._verify_correctness(i, target))

i = torchtrt.Input(torch.randn(shape).shape)
self.assertTrue(self._verify_correctness(i, target))

i = torchtrt.Input(shape=shape)
self.assertTrue(self._verify_correctness(i, target))

i = torchtrt.Input(shape=tuple(shape))
self.assertTrue(self._verify_correctness(i, target))

i = torchtrt.Input(shape=torch.randn(shape).shape)
self.assertTrue(self._verify_correctness(i, target))

def test_data_type(self):
shape = [1, 3, 255, 255]
target = {
"min": shape,
"opt": shape,
"max": shape,
"input_is_dynamic": False,
"dtype": torchtrt.dtype.half,
"format": torchtrt.TensorFormat.contiguous,
"explicit_set_dtype": True
}

i = torchtrt.Input(shape, dtype=torchtrt.dtype.half)
self.assertTrue(self._verify_correctness(i, target))

i = torchtrt.Input(shape, dtype=torch.half)
self.assertTrue(self._verify_correctness(i, target))

def test_tensor_format(self):
shape = [1, 3, 255, 255]
target = {
"min": shape,
"opt": shape,
"max": shape,
"input_is_dynamic": False,
"dtype": torchtrt.dtype.unknown,
"format": torchtrt.TensorFormat.channels_last,
"explicit_set_dtype": False
}

i = torchtrt.Input(shape, format=torchtrt.TensorFormat.channels_last)
self.assertTrue(self._verify_correctness(i, target))

i = torchtrt.Input(shape, format=torch.channels_last)
self.assertTrue(self._verify_correctness(i, target))

def test_dynamic_shape(self):
min_shape = [1, 3, 128, 128]
opt_shape = [1, 3, 256, 256]
max_shape = [1, 3, 512, 512]
target = {
"min": min_shape,
"opt": opt_shape,
"max": max_shape,
"input_is_dynamic": True,
"dtype": torchtrt.dtype.unknown,
"format": torchtrt.TensorFormat.contiguous,
"explicit_set_dtype": False
}

i = torchtrt.Input(min_shape=min_shape, opt_shape=opt_shape, max_shape=max_shape)
self.assertTrue(self._verify_correctness(i, target))

i = torchtrt.Input(min_shape=tuple(min_shape), opt_shape=tuple(opt_shape), max_shape=tuple(max_shape))
self.assertTrue(self._verify_correctness(i, target))

tensor_shape = lambda shape: torch.randn(shape).shape
i = torchtrt.Input(min_shape=tensor_shape(min_shape),
opt_shape=tensor_shape(opt_shape),
max_shape=tensor_shape(max_shape))
self.assertTrue(self._verify_correctness(i, target))

if __name__ == "__main__":
unittest.main()
Loading

0 comments on commit 2be072a

Please sign in to comment.