Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*.weight
*.nsys-rep
*.pkl
*.pt
*.pt2
*.xlsx
*.sarif
*.sqlitest
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOGS.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Change Logs
===========

0.8.3
+++++

* :pr:`304`: improves side-by-side comparison

0.8.2
+++++

Expand Down
2 changes: 1 addition & 1 deletion _doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ The function replaces dynamic dimensions defined as strings by
Older versions
==============

* `0.8.3 <../v0.8.3/index.html>`_
* `0.8.2 <../v0.8.2/index.html>`_
* `0.8.1 <../v0.8.1/index.html>`_
* `0.7.16 <../v0.7.16/index.html>`_
* `0.6.3 <../v0.6.3/index.html>`_
* `0.5.0 <../v0.5.0/index.html>`_
Expand Down
2 changes: 2 additions & 0 deletions _unittests/ut_export/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ def test_tiny_llm_to_onnx(self):
diff = max_diff(expected, got)
assert diff["abs"] <= 1e-5, f"diff={diff}"

self.clean_dump()


if __name__ == "__main__":
unittest.main(verbosity=2)
31 changes: 25 additions & 6 deletions _unittests/ut_helpers/test_bench_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,35 +109,51 @@ def test_make_configs_replace(self):
def test_max_diff(self):
self.assertEqual(
max_diff(torch.Tensor([1, 2]), torch.Tensor([1, 2])),
{"abs": 0.0, "rel": 0.0, "sum": 0.0, "n": 2.0, "dnan": 0.0, "argm": (0,)},
{
"abs": 0.0,
"rel": 0.0,
"sum": 0.0,
"n": 2.0,
"dnan": 0.0,
"argm": (0,),
"dev": 0,
},
)
self.assertEqual(
max_diff(
(torch.Tensor([1, 2]),),
(torch.Tensor([1, 2])),
),
{"abs": 0.0, "rel": 0.0, "sum": 0.0, "n": 2.0, "dnan": 0.0, "argm": (0,)},
{
"abs": 0.0,
"rel": 0.0,
"sum": 0.0,
"n": 2.0,
"dnan": 0.0,
"argm": (0,),
"dev": 0,
},
)
self.assertEqual(
max_diff(
(torch.Tensor([1, 2]), (torch.Tensor([1, 2]),)),
(torch.Tensor([1, 2]), (torch.Tensor([1, 2]),)),
),
{"abs": 0.0, "rel": 0.0, "sum": 0.0, "n": 4.0, "dnan": 0.0},
{"abs": 0.0, "rel": 0.0, "sum": 0.0, "n": 4.0, "dnan": 0.0, "dev": 0},
)
self.assertEqual(
max_diff(
{"a": torch.Tensor([1, 2])},
{"a": torch.Tensor([1, 2])},
),
{"abs": 0.0, "rel": 0.0, "sum": 0.0, "n": 2.0, "dnan": 0.0},
{"abs": 0.0, "rel": 0.0, "sum": 0.0, "n": 2.0, "dnan": 0.0, "dev": 0},
)
self.assertEqual(
max_diff(
{"a": torch.Tensor([1, 2])},
[torch.Tensor([1, 2])],
),
{"abs": 0.0, "rel": 0.0, "sum": 0.0, "n": 2.0, "dnan": 0.0},
{"abs": 0.0, "rel": 0.0, "sum": 0.0, "n": 2.0, "dnan": 0.0, "dev": 0},
)
self.assertEqual(
max_diff(
Expand All @@ -150,6 +166,7 @@ def test_max_diff(self):
"n": 2.0,
"rel": 0.9999999997999001,
"sum": 9999999998.0,
"dev": 0,
},
)

Expand All @@ -164,7 +181,9 @@ def test_max_diff_dynamic_cache(self):
flatten=True,
verbose=10,
)
self.assertEqual(md, {"abs": 0.0, "rel": 0.0, "sum": 0.0, "n": 10.0, "dnan": 0})
self.assertEqual(
md, {"abs": 0.0, "rel": 0.0, "sum": 0.0, "n": 10.0, "dnan": 0, "dev": 0}
)


if __name__ == "__main__":
Expand Down
26 changes: 26 additions & 0 deletions _unittests/ut_helpers/test_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
hide_stdout,
requires_onnx,
requires_transformers,
requires_cuda,
)
from onnx_diagnostic.helpers.helper import (
string_type,
Expand Down Expand Up @@ -199,6 +200,31 @@ def test_flatten(self):
d = string_diff(diff)
self.assertIsInstance(d, str)

@hide_stdout()
def test_maxdiff_device(self):
inputs = (torch.arange(2), torch.cos(torch.arange(3)))
diff = max_diff(inputs, inputs, flatten=True, verbose=10)
self.assertEqual(diff["abs"], 0)
self.assertEqual(diff["dev"], 0)

@hide_stdout()
@requires_cuda()
def test_maxdiff_device_cuda(self):
diff = max_diff(torch.ones((2,)).cuda(), torch.ones((2,)), verbose=10)
self.assertEqual(diff["dev"], 1)
inputs = (torch.arange(2), torch.cos(torch.arange(3)))
inputs2 = (inputs[0].cuda(), inputs[1].cuda())
diff = max_diff(inputs, inputs2, verbose=10)
self.assertEqual(diff["abs"], 0)
self.assertEqual(diff["dev"], 2)
inputs2 = (inputs[0], inputs[1].cuda())
diff = max_diff(inputs, inputs2, verbose=10)
self.assertEqual(diff["abs"], 0)
self.assertEqual(diff["dev"], 1)
diff = max_diff(inputs2, inputs2, verbose=10)
self.assertEqual(diff["abs"], 0)
self.assertEqual(diff["dev"], 0)

def test_flatten_cache(self):
cache = make_dynamic_cache([(torch.ones((5, 6, 5, 6)), torch.ones((5, 6, 5, 6)) + 2)])
flat = flatten_object(cache, drop_keys=True)
Expand Down
5 changes: 5 additions & 0 deletions _unittests/ut_helpers/test_log_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ def test_cube_logs_excel(self):
verbose=1,
)
self.assertExists(output)
self.clean_dump()

@hide_stdout()
def test_enumerate_csv_files(self):
Expand All @@ -210,6 +211,7 @@ def test_enumerate_csv_files(self):
cube.load(verbose=1)
self.assertEqual((3, 11), cube.shape)
self.assertIn("RAWFILENAME", cube.data.columns)
self.clean_dump()

def test_cube_logs_performance1(self):
output = self.get_dump_file("test_cube_logs_performance1.xlsx")
Expand All @@ -235,6 +237,7 @@ def test_cube_logs_performance1(self):
],
)
self.assertExists(output)
self.clean_dump()

def test_cube_logs_performance2(self):
output = self.get_dump_file("test_cube_logs_performance2.xlsx")
Expand Down Expand Up @@ -470,6 +473,7 @@ def test_historical_cube_time_mask(self):
)
cube = CubeLogs(df, keys=["^m_*", "exporter"], time="date").load()
cube.to_excel(output, views=["time_p"], time_mask=True, verbose=1)
self.clean_dump()

def test_cube_sbs_no_time(self):
df = pandas.DataFrame(
Expand Down Expand Up @@ -532,6 +536,7 @@ def test_cube_sbs_no_time(self):
verbose=0,
sbs=dict(CFA=dict(exporter="E1", opt="O"), CFB=dict(exporter="E2", opt="O")),
)
self.clean_dump()

def test_cube_sbs_with_time(self):
df = pandas.DataFrame(
Expand Down
1 change: 1 addition & 0 deletions _unittests/ut_helpers/test_ort_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ def test_profiling(self):
got = wrap.run(None, feeds)
self.assertIsInstance(got[0], torch.Tensor)
self.assertEqualArray(expected[0], got[0])
self.clean_dump()


if __name__ == "__main__":
Expand Down
4 changes: 4 additions & 0 deletions _unittests/ut_helpers/test_torch_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ def forward(self, x, y):
self.assertEqualAny(restored["main", 1, "I"], (inputs, {}))
self.assertEqualAny(restored["main", 0, "O"], res1)
self.assertEqualAny(restored["main", 0, "O"], res2)
self.clean_dump()

@hide_stdout()
def test_steal_forward_dump_file_steal_append(self):
Expand Down Expand Up @@ -181,6 +182,7 @@ def forward(self, x, y):
{("", 1, "I"), ("", 1, "O"), "sx", ("", 0, "O"), "sx_1", ("", 0, "I")},
set(restored),
)
self.clean_dump()

@hide_stdout()
def test_steal_forward_dump_file_steal_append_drop(self):
Expand Down Expand Up @@ -214,6 +216,7 @@ def forward(self, x, y):
first = restored[("", 0, "I")]
_a, kws = first
self.assertNotIn("x", kws)
self.clean_dump()

@hide_stdout()
def test_steal_forward_submodules(self):
Expand Down Expand Up @@ -257,6 +260,7 @@ def forward(self, x, y):
),
len(sorted(restored)),
)
self.clean_dump()

def test_replace_string_by_dynamic(self):
example = {
Expand Down
35 changes: 34 additions & 1 deletion _unittests/ut_reference/test_onnxruntime_evaluator.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import unittest
from typing import Optional
import numpy as np
import onnx
import onnx.helper as oh
import torch
import onnxruntime
from onnx_diagnostic.ext_test_case import ExtTestCase, hide_stdout
from onnx_diagnostic.ext_test_case import ExtTestCase, hide_stdout, ignore_warnings
from onnx_diagnostic.helpers.onnx_helper import from_array_extended
from onnx_diagnostic.reference import (
OnnxruntimeEvaluator,
Expand All @@ -22,6 +23,14 @@


class TestOnnxruntimeEvaluator(ExtTestCase):
def _range(self, *shape, bias: Optional[float] = None):
n = np.prod(shape)
x = np.arange(n).astype(np.float32) / n
if bias:
x = x + bias
return x.reshape(tuple(shape)).astype(np.float32)

@ignore_warnings(FutureWarning)
def test_ort_eval_scan_cdist_add(self):

def dist(unused: torch.Tensor, x: torch.Tensor, samex: torch.Tensor):
Expand Down Expand Up @@ -69,6 +78,7 @@ def forward(self, x):
got = orte.run(None, {name: x.numpy()})[0]
self.assertEqualArray(expected, got)

@ignore_warnings((UserWarning, FutureWarning))
def test_ort_eval_cond(self):
import torch

Expand Down Expand Up @@ -180,6 +190,7 @@ def test_constant_bool_input(self):
self.assertEqual(got.dtype, torch.bool)
self.assertEqual(got[0], True)

@hide_stdout()
def test_ort_eval_loop(self):
model = torch.nn.EmbeddingBag(num_embeddings=49157, embedding_dim=32, mode="sum")
a = torch.tensor([[39906, 39906]]).long()
Expand Down Expand Up @@ -226,6 +237,28 @@ def test_report_results_comparison_ort(self):
self.assertLess(d[(0, "nx"), "r_cos"], 1e-6)
self.assertLess(d[(2, "u"), "r_exp"], 1e-6)

@hide_stdout()
def test_skip_layer_normalization(self):
node = oh.make_node(
"SkipLayerNormalization",
["x", "skip", "beta", "gamma", "bias"],
["Z"],
epsilon=1.0e-5,
domain="com.microsoft",
)
feeds = dict(
x=self._range(2, 3, 8),
skip=self._range(2, 3, 8, bias=3),
beta=self._range(8, bias=1),
gamma=self._range(8, bias=2),
bias=self._range(8, bias=0.1),
)
ref = ExtendedReferenceEvaluator(node)
expected = ref.run(None, feeds)
rt = OnnxruntimeEvaluator(node, verbose=10, opsets={"": 22})
got = rt.run(None, feeds)
self.assertEqualAny(expected, got, atol=1e-4)


if __name__ == "__main__":
unittest.main(verbosity=2)
4 changes: 3 additions & 1 deletion _unittests/ut_tasks/try_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ def _config_reduction(config, task):
hidden_states=torch.rand((1292, 1176), dtype=torch_dtype).to(device),
grid_thw=torch.tensor([[1, 34, 38]], dtype=torch.int64).to(device),
)
print("-- save inputs")
torch.save(inputs, self.get_dump_file("qwen_2_5_vl_instruct_visual.inputs.pt"))

print(f"-- inputs: {self.string_type(inputs, with_shape=True)}")
# this is too long
Expand Down Expand Up @@ -120,7 +122,7 @@ def _config_reduction(config, task):
filename=filename,
exporter=exporter,
verbose=1,
save_ep=fileep,
save_ep=(fileep, 2**35),
target_opset=22,
optimize=True,
)
Expand Down
2 changes: 1 addition & 1 deletion _unittests/ut_torch_export_patches/test_patch_torch.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ def _batch1(t):
got = ep.module()(**torch_deepcopy(inputs))
self.assertEqualArrayAny(expected, got)

@requires_torch("2.9", "Eq(s3, Max(s10, s3)) is inconsistent!")
@requires_torch("2.11", "Eq(s3, Max(s10, s3)) is inconsistent!, until we know more")
def test_patch_tiny_llm_dim_meta_level_1(self):
class Model(torch.nn.Module):
def forward(self, x, ind1, ind2):
Expand Down
2 changes: 2 additions & 0 deletions _unittests/ut_torch_export_patches/test_patch_transformers.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ def forward(
atol=1e-3,
rtol=1,
)
self.clean_dump()

@requires_transformers("4.99")
@requires_torch("2.9.99")
Expand Down Expand Up @@ -508,6 +509,7 @@ def test_qwen2_5_vl_vision_attention_iteration(self):
atol=1e-3,
rtol=1,
)
self.clean_dump()


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions _unittests/ut_torch_models/test_hghub_mode_rewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ def test_export_rewriting_bart(self):
data = get_untrained_model_with_inputs(mid, verbose=1)
model, inputs, ds = data["model"], data["inputs"], data["dynamic_shapes"]
dump_folder = self.get_dump_file("test_export_rewritin_bart")
print(self.string_type(inputs))
print(self.string_type(ds))
print("--", self.string_type(inputs))
print("--", self.string_type(ds))
with torch_export_patches(
patch_transformers=True, rewrite=model, dump_rewriting=dump_folder
):
Expand Down
7 changes: 5 additions & 2 deletions _unittests/ut_torch_models/test_validate_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ def test_validate_tiny_llms_bfloat16(self):
)
self.assertLess(summary["disc_onnx_ort_run_abs"], 2e-2)
self.assertIn("onnx_filename", data)
self.clean_dump()

@unittest.skipIf(torch29_and_tr_main, "combination not working")
@requires_transformers("4.53")
@requires_torch("2.8.99")
@requires_transformers("4.57") # 4.53 works for some jobs fails due to no space left
@requires_torch("2.9.99") # 2.9 works for some jobs fails due to no space left
@requires_experimental()
@hide_stdout()
def test_validate_microsoft_phi4_reasoning(self):
Expand All @@ -65,6 +66,7 @@ def test_validate_microsoft_phi4_reasoning(self):
)
self.assertLess(summary["disc_onnx_ort_run_abs"], 2e-5)
self.assertIn("onnx_filename", data)
self.clean_dump()

@unittest.skipIf(torch29_and_tr_main, "combination not working")
@requires_transformers("4.53")
Expand All @@ -87,6 +89,7 @@ def test_validate_microsoft_phi3_mini_128k(self):
)
self.assertLess(summary["disc_onnx_ort_run_abs"], 2e-5)
self.assertIn("onnx_filename", data)
self.clean_dump()


if __name__ == "__main__":
Expand Down
Loading
Loading