Date: Tue, 21 Apr 2026 18:57:13 +0000 From: Yuri Victorovich <yuri@FreeBSD.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org Subject: git: c00e155769e3 - main - misc/py-pytorch: Fix many tests; Other improvements Message-ID: <69e7c889.19566.45f7dde6@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by yuri: URL: https://cgit.FreeBSD.org/ports/commit/?id=c00e155769e3d6b63ad25b149b198199df97c829 commit c00e155769e3d6b63ad25b149b198199df97c829 Author: Yuri Victorovich <yuri@FreeBSD.org> AuthorDate: 2026-04-21 18:56:33 +0000 Commit: Yuri Victorovich <yuri@FreeBSD.org> CommitDate: 2026-04-21 18:57:10 +0000 misc/py-pytorch: Fix many tests; Other improvements --- misc/py-pytorch/Makefile | 6 +- misc/py-pytorch/files/patch-pytest.ini | 12 +++ .../files/patch-test_dynamo_test__aot__autograd.py | 18 +++++ .../files/patch-test_dynamo_test__ctx__manager.py | 34 ++++++++ ...patch-test_dynamo_test__guard__serialization.py | 26 +++++++ .../files/patch-test_dynamo_test__repros.py | 10 +++ .../files/patch-test_jit_test__backends.py | 20 +++++ misc/py-pytorch/files/patch-test_jit_test__with.py | 21 +++++ misc/py-pytorch/files/patch-test_run__test.py | 91 +++++++++++----------- .../files/patch-test_test__cpp__extensions__jit.py | 12 +++ misc/py-pytorch/files/patch-test_test__fx.py | 43 ++++++++++ misc/py-pytorch/files/patch-test_test__jit.py | 35 +++++++++ .../files/patch-test_test__jit__profiling.py | 16 ++++ .../files/patch-test_test__multiprocessing.py | 21 +++++ misc/py-pytorch/files/patch-test_test__torch.py | 12 +++ ...orch___inductor_compile__worker_____main____.py | 11 +++ .../files/patch-torch___inductor_cpp__builder.py | 13 ++++ .../files/patch-torch___inductor_cpu__vec__isa.py | 31 ++++++++ misc/py-pytorch/files/patch-torch___inductor_ir.py | 11 +++ .../files/patch-torch___inductor_kernel_mm.py | 11 +++ ...atch-torch___inductor_runtime_triton__compat.py | 12 +++ .../files/patch-torch___utils__internal.py | 14 ++++ .../files/patch-torch_csrc_Exceptions.cpp | 34 ++++++++ .../py-pytorch/files/patch-torch_csrc_Exceptions.h | 86 ++++++++++++++++++++ .../files/patch-torch_csrc_jit_ir_attributes.h | 36 +++++++++ misc/py-pytorch/files/patch-torch_csrc_jit_ir_ir.h | 26 +++++++ .../patch-torch_csrc_jit_passes_inplace__check.cpp | 21 +++++ ...istributed_elastic_multiprocessing_redirects.py | 13 ++++ misc/py-pytorch/files/patch-torch_jit___trace.py | 73 ++++++++++++++++- ...ch-torch_testing___internal_torchbind__impls.py | 11 +++ .../py-pytorch/files/patch-torch_utils___triton.py | 14 ++++ .../files/patch-torch_utils_cpp__extension.py | 31 ++++++++ 32 files changed, 778 insertions(+), 47 deletions(-) diff --git a/misc/py-pytorch/Makefile b/misc/py-pytorch/Makefile index 0a8ea89d294c..b8a00e48f67d 100644 --- a/misc/py-pytorch/Makefile +++ b/misc/py-pytorch/Makefile @@ -1,6 +1,7 @@ PORTNAME= pytorch DISTVERSIONPREFIX= v DISTVERSION= 2.11.0 +PORTREVISION= 1 CATEGORIES= misc # machine-learning MASTER_SITES= https://github.com/pytorch/pytorch/releases/download/v${DISTVERSION}/ PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX} @@ -81,7 +82,10 @@ BINARY_ALIAS= make=${GMAKE} POST_PLIST= fix-plist -TEST_ENV= ${MAKE_ENV} PYTHONPATH=${STAGEDIR}${PYTHONPREFIX_SITELIBDIR} +TEST_DEPENDS= ${PYTHON_PKGNAMEPREFIX}pytest-rerunfailures>0:devel/py-pytest-rerunfailures@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}pytest-xdist>0:devel/py-pytest-xdist@${PY_FLAVOR} +TEST_ENV= ${MAKE_ENV} PYTHONPATH=${STAGEDIR}${PYTHONPREFIX_SITELIBDIR} \ + TORCHINDUCTOR_CACHE_DIR=${WRKDIR}/torchinductor_cache TEST_WRKSRC= ${WRKSRC}/test OPTIONS_DEFINE= VULKAN diff --git a/misc/py-pytorch/files/patch-pytest.ini b/misc/py-pytorch/files/patch-pytest.ini new file mode 100644 index 000000000000..dcc0981f4001 --- /dev/null +++ b/misc/py-pytorch/files/patch-pytest.ini @@ -0,0 +1,12 @@ +--- pytest.ini.orig 2026-04-19 05:34:30 UTC ++++ pytest.ini +@@ -10,6 +10,9 @@ addopts = + -p no:warnings + # Use custom pytest shard located in test/pytest_shard_custom.py instead + -p no:pytest-shard ++ # Disable coverage collection (pytest-enabler auto-enables it; causes SIGBUS on FreeBSD) ++ -p no:enabler ++ -p no:cov + # don't rewrite assertions (usually not a problem in CI due to differences in imports, see #95844) + --assert=plain + testpaths = diff --git a/misc/py-pytorch/files/patch-test_dynamo_test__aot__autograd.py b/misc/py-pytorch/files/patch-test_dynamo_test__aot__autograd.py new file mode 100644 index 000000000000..47c67c05b03e --- /dev/null +++ b/misc/py-pytorch/files/patch-test_dynamo_test__aot__autograd.py @@ -0,0 +1,18 @@ +--- test/dynamo/test_aot_autograd.py.orig 2026-04-19 12:47:58 UTC ++++ test/dynamo/test_aot_autograd.py +@@ -1,6 +1,7 @@ import re + # Owner(s): ["module: dynamo"] + import copy + import re ++import sys + import unittest + from textwrap import dedent + from unittest.mock import patch +@@ -1009,6 +1010,7 @@ SeqNr|OrigAten|SrcFn|FwdSrcFn + + # set donated_buffer=False due to create_graph=True + @torch._functorch.config.patch("donated_buffer", False) ++ @unittest.skipIf(sys.platform.startswith("freebsd"), "Kineto causes SIGABRT on FreeBSD") + def test_eager_sequence_nr(self): + class Model(torch.nn.Module): + def __init__(self) -> None: diff --git a/misc/py-pytorch/files/patch-test_dynamo_test__ctx__manager.py b/misc/py-pytorch/files/patch-test_dynamo_test__ctx__manager.py new file mode 100644 index 000000000000..8320fb30997a --- /dev/null +++ b/misc/py-pytorch/files/patch-test_dynamo_test__ctx__manager.py @@ -0,0 +1,34 @@ +--- test/dynamo/test_ctx_manager.py.orig 2026-04-19 12:47:58 UTC ++++ test/dynamo/test_ctx_manager.py +@@ -167,6 +167,7 @@ class CtxManagerTests(torch._dynamo.test_case.TestCase + opt_fn(a) + self.assertEqual(cnts.frame_count, 2) + ++ @unittest.skipIf(sys.platform.startswith("freebsd"), "Kineto causes SIGABRT on FreeBSD") + def test_torch_profiler(self): + # wrap torch.profiler.* as NullContextVariable and do nothing + def fn(x): +@@ -187,6 +188,7 @@ class CtxManagerTests(torch._dynamo.test_case.TestCase + self.assertTrue(same(ref, res)) + self.assertEqual(cnts.frame_count, 2) + ++ @unittest.skipIf(sys.platform.startswith("freebsd"), "Kineto causes SIGABRT on FreeBSD") + def test_autograd_profiler(self): + # wrap torch.autograd.profiler.* as NullContextVariable and do nothing + def fn(x): +@@ -583,6 +585,7 @@ class CtxManagerTests(torch._dynamo.test_case.TestCase + res = opt_fn(x) + self.assertEqual(ref, res) + ++ @unittest.skipIf(sys.platform.startswith("freebsd"), "Kineto causes SIGABRT on FreeBSD") + def test_autograd_profiler_enabled(self): + def fn(x): + if torch.autograd._profiler_enabled(): +@@ -1830,6 +1833,7 @@ class GraphModule(torch.nn.Module): + opt_f = torch.compile(f, backend="eager") + opt_f(torch.randn(2, 2)) + ++ @unittest.skipIf(sys.platform.startswith("freebsd"), "Kineto causes SIGABRT on FreeBSD") + def test_torch_profiler_use_after_with_block(self): + counters.clear() + diff --git a/misc/py-pytorch/files/patch-test_dynamo_test__guard__serialization.py b/misc/py-pytorch/files/patch-test_dynamo_test__guard__serialization.py new file mode 100644 index 000000000000..ba517fc6e912 --- /dev/null +++ b/misc/py-pytorch/files/patch-test_dynamo_test__guard__serialization.py @@ -0,0 +1,26 @@ +--- test/dynamo/test_guard_serialization.py.orig 2026-04-19 12:47:58 UTC ++++ test/dynamo/test_guard_serialization.py +@@ -1506,6 +1506,7 @@ class TestGuardSerialization(TestGuardSerializationBas + True, + ) + ++ @unittest.skipIf(sys.platform.startswith("freebsd"), "Gloo does not support FreeBSD") + def test_ddp_module(self): + import torch.distributed as dist + +@@ -1558,6 +1559,7 @@ class TestGuardSerialization(TestGuardSerializationBas + True, + ) + ++ @unittest.skipIf(sys.platform.startswith("freebsd"), "Gloo does not support FreeBSD") + def test_unserializable_sharded_tensor(self): + import torch.distributed as dist + +@@ -1675,6 +1677,7 @@ class TestGuardSerialization(TestGuardSerializationBas + ref, loaded, {"inputs": Inputs(x, torch.cuda.Stream())}, True + ) + ++ @unittest.skipIf(sys.platform.startswith("freebsd"), "Gloo does not support FreeBSD") + def test_unused_process_group(self): + import torch.distributed as dist + diff --git a/misc/py-pytorch/files/patch-test_dynamo_test__repros.py b/misc/py-pytorch/files/patch-test_dynamo_test__repros.py new file mode 100644 index 000000000000..0809cd5f470d --- /dev/null +++ b/misc/py-pytorch/files/patch-test_dynamo_test__repros.py @@ -0,0 +1,10 @@ +--- test/dynamo/test_repros.py.orig 2026-04-19 12:47:58 UTC ++++ test/dynamo/test_repros.py +@@ -6105,6 +6105,7 @@ def forward(self, s77 : torch.SymInt, s27 : torch.SymI + self.assertEqual(result, result_test) + self.assertEqual(x, x_test) + ++ @unittest.skipIf(sys.platform.startswith("freebsd"), "Kineto causes SIGABRT on FreeBSD") + def test_aot_autograd_runtime_wrapper_prologue_profiled(self): + # Names for prologue profiling event + prologue_name = "AOTDispatcher Runtime Wrapper Prologue" diff --git a/misc/py-pytorch/files/patch-test_jit_test__backends.py b/misc/py-pytorch/files/patch-test_jit_test__backends.py new file mode 100644 index 000000000000..3277d9e15397 --- /dev/null +++ b/misc/py-pytorch/files/patch-test_jit_test__backends.py @@ -0,0 +1,20 @@ +--- test/jit/test_backends.py.orig 2026-04-18 20:22:08 UTC ++++ test/jit/test_backends.py +@@ -71,6 +71,8 @@ class JitBackendTestCase(JitTestCase): + def setUp(self): + super().setUp() + lib_file_path = find_library_location("libjitbackend_test.so") ++ if not lib_file_path.exists(): ++ raise unittest.SkipTest(f"libjitbackend_test.so not found (C++ test library)") + torch.ops.load_library(str(lib_file_path)) + # Subclasses are expected to set up three variables in their setUp methods: + # module - a regular, Python version of the module being tested +@@ -514,6 +516,8 @@ class JitBackendTestCaseWithCompiler(JitTestCase): + def setUp(self): + super().setUp() + lib_file_path = find_library_location("libbackend_with_compiler.so") ++ if not lib_file_path.exists(): ++ raise unittest.SkipTest(f"libbackend_with_compiler.so not found (C++ test library)") + torch.ops.load_library(str(lib_file_path)) + # Subclasses are expected to set up four variables in their setUp methods: + # module - a regular, Python version of the module being tested diff --git a/misc/py-pytorch/files/patch-test_jit_test__with.py b/misc/py-pytorch/files/patch-test_jit_test__with.py new file mode 100644 index 000000000000..e03d0c71a973 --- /dev/null +++ b/misc/py-pytorch/files/patch-test_jit_test__with.py @@ -0,0 +1,21 @@ +--- test/jit/test_with.py.orig 2026-04-18 21:49:29 UTC ++++ test/jit/test_with.py +@@ -3,6 +3,7 @@ import sys + + import os + import sys ++import unittest + from typing import Any, List + + import torch +@@ -609,6 +610,10 @@ class TestWith(JitTestCase): + self.assertFalse(w.requires_grad) + + @skipIfTorchDynamo("Torchdynamo cannot correctly handle profiler.profile calls") ++ @unittest.skipIf( ++ sys.platform.startswith("freebsd"), ++ "Hangs on FreeBSD due to profiler/JIT interaction deadlock", ++ ) + def test_with_record_function(self): + """ + Check that torch.autograd.profiler.record_function context manager is diff --git a/misc/py-pytorch/files/patch-test_run__test.py b/misc/py-pytorch/files/patch-test_run__test.py index 4887f9c5e63e..8968c9b93aa7 100644 --- a/misc/py-pytorch/files/patch-test_run__test.py +++ b/misc/py-pytorch/files/patch-test_run__test.py @@ -1,59 +1,60 @@ ---- test/run_test.py.orig 2026-04-17 23:39:17 UTC +--- test/run_test.py.orig 2026-03-23 18:40:42 UTC +++ test/run_test.py -@@ -1244,21 +1244,10 @@ def get_pytest_args(options, is_cpp_test=False, is_dis +@@ -1142,6 +1142,12 @@ def run_doctests(test_module, test_directory, options) + else: + enabled["onnx"] = True - - def get_pytest_args(options, is_cpp_test=False, is_distributed_test=False): -- if is_distributed_test: -- # Distributed tests do not support rerun, see https://github.com/pytorch/pytorch/issues/162978 -- rerun_options = ["-x", "--reruns=0"] -- elif RERUN_DISABLED_TESTS: -- # ASAN tests are too slow, so running them x50 will cause the jobs to timeout after -- # 3+ hours. So, let's opt for less number of reruns. We need at least 150 instances of the -- # test every 2 weeks to satisfy the SQL query (15 x 14 = 210). -- count = 15 if TEST_WITH_ASAN else 50 -- # When under rerun-disabled-tests mode, run the same tests multiple times to determine their -- # flakiness status. Default to 50 re-runs -- rerun_options = ["--flake-finder", f"--flake-runs={count}"] -+ if is_distributed_test or RERUN_DISABLED_TESTS: -+ rerun_options = ["-x"] - else: -- # When under the normal mode, retry a failed test 2 more times. -x means stop at the first -- # failure -- rerun_options = ["-x", "--reruns=2"] -+ rerun_options = ["-x"] - - pytest_args = [ - "-vv", -@@ -1277,7 +1266,7 @@ def get_pytest_args(options, is_cpp_test=False, is_dis - # Add the option to generate XML test report here as C++ tests - # won't go into common_utils - test_report_path = get_report_path(pytest=True) -- pytest_args.extend(["--junit-xml-reruns", test_report_path]) -+ pytest_args.extend(["--junit-xml", test_report_path]) - - if options.pytest_k_expr: - pytest_args.extend(["-k", options.pytest_k_expr]) -@@ -1812,6 +1801,13 @@ def get_selected_tests(options) -> list[str]: ++ try: ++ import torchdata.datapipes # NOQA: F401 ++ except ImportError: ++ # torchdata.datapipes was removed in newer versions; skip datapipes doctests ++ exclude_module_list.append("torch.utils.data.datapipes.*") ++ + # Set doctest environment variables + if enabled["cuda"]: + os.environ["TORCH_DOCTEST_CUDA"] = "1" +@@ -1812,6 +1818,35 @@ def get_selected_tests(options) -> list[str]: "Skip distributed tests on s390x", ) + if sys.platform.startswith("freebsd"): + selected_tests = exclude_tests( ++ ["profiler/test_profiler", "dynamo/test_profiler"], ++ selected_tests, ++ "Skip profiler tests on FreeBSD (Kineto causes SIGABRT)", ++ ) ++ selected_tests = exclude_tests( + DISTRIBUTED_TESTS, + selected_tests, -+ "Skip distributed tests on FreeBSD (gloo unsupported)", ++ "Skip distributed tests on FreeBSD (Gloo does not support FreeBSD)", ++ ) ++ selected_tests = exclude_tests( ++ ["test_ci_sanity_check_fail"], ++ selected_tests, ++ "Skip CI-only sanity check on FreeBSD (requires CI env var)", ++ ) ++ selected_tests = exclude_tests( ++ [ ++ "cpp_extensions/libtorch_agn_2_10_extension/test_version_compatibility", ++ ], ++ selected_tests, ++ "Skip g++ version-compatibility tests on FreeBSD (g++ not available)", ++ ) ++ selected_tests = exclude_tests( ++ ["test_vulkan"], ++ selected_tests, ++ "Skip Vulkan tests on FreeBSD (SIGSEGV in Vulkan driver teardown)", + ) + # skip all distributed tests if distributed package is not available. if not dist.is_available(): selected_tests = exclude_tests( -@@ -2100,8 +2096,6 @@ def main(): - - - def main(): -- check_pip_packages() -- - options = parse_args() - tests_to_include_env = os.environ.get("TESTS_TO_INCLUDE", "").strip() - if tests_to_include_env: +@@ -2086,7 +2121,7 @@ def check_pip_packages() -> None: + def check_pip_packages() -> None: + packages = [ + "pytest-rerunfailures", +- "pytest-flakefinder", ++ # pytest-flakefinder is not available as a FreeBSD port; skip check + "pytest-xdist", + ] + try: diff --git a/misc/py-pytorch/files/patch-test_test__cpp__extensions__jit.py b/misc/py-pytorch/files/patch-test_test__cpp__extensions__jit.py new file mode 100644 index 000000000000..0f93187d98b1 --- /dev/null +++ b/misc/py-pytorch/files/patch-test_test__cpp__extensions__jit.py @@ -0,0 +1,12 @@ +--- test/test_cpp_extensions_jit.py.orig 2026-04-18 16:52:06 UTC ++++ test/test_cpp_extensions_jit.py +@@ -733,7 +733,8 @@ class TestCppExtensionJIT(common.TestCase): + self.assertEqual(module.f(), 789) + + @unittest.skipIf( +- "utf" not in locale.getlocale()[1].lower(), "Only test in UTF-8 locale" ++ not (locale.getlocale()[1] and "utf" in locale.getlocale()[1].lower()), ++ "Only test in UTF-8 locale", + ) + def test_load_with_non_platform_default_encoding(self): + # Assume the code is saved in UTF-8, but the locale is set to a different encoding. diff --git a/misc/py-pytorch/files/patch-test_test__fx.py b/misc/py-pytorch/files/patch-test_test__fx.py new file mode 100644 index 000000000000..dc6c33660421 --- /dev/null +++ b/misc/py-pytorch/files/patch-test_test__fx.py @@ -0,0 +1,43 @@ +--- test/test_fx.py.orig 2026-04-18 17:21:07 UTC ++++ test/test_fx.py +@@ -248,9 +248,12 @@ class TestFX(JitTestCase): + ) + torch.fx.proxy.TracerBase.check_mutable_operations = True + ++ self._torchbind_test_loaded = False + if not (IS_FBCODE or IS_WINDOWS or IS_MACOS): + lib_file_path = find_library_location("libtorchbind_test.so") +- torch.ops.load_library(str(lib_file_path)) ++ if lib_file_path.exists(): ++ torch.ops.load_library(str(lib_file_path)) ++ self._torchbind_test_loaded = True + + def tearDown(self): + super().tearDown() +@@ -869,7 +872,7 @@ class TestFX(JitTestCase): + self.checkGraphModule(m, (a, b)) + + def test_native_callable(self): +- if IS_FBCODE or IS_WINDOWS or IS_MACOS: ++ if IS_FBCODE or IS_WINDOWS or IS_MACOS or not self._torchbind_test_loaded: + raise unittest.SkipTest("non-portable load_library call used in test") + # This test exercises the case where we use FX to translate from Python + # code to some native callable object +@@ -3062,7 +3065,7 @@ class TestFX(JitTestCase): + node.__update_args_kwargs((), {}) + + def test_torchbind_class_attribute_in_fx(self): +- if IS_FBCODE or IS_WINDOWS or IS_MACOS: ++ if IS_FBCODE or IS_WINDOWS or IS_MACOS or not self._torchbind_test_loaded: + self.skipTest( + "torch.classes._TorchScriptTesting._StackString is registered, skipping" + ) +@@ -3079,7 +3082,7 @@ class TestFX(JitTestCase): + self.checkGraphModule(m, ()) + + def test_torchbind_class_attribute_in_fx_tensor_arg(self): +- if IS_FBCODE or IS_WINDOWS or IS_MACOS: ++ if IS_FBCODE or IS_WINDOWS or IS_MACOS or not self._torchbind_test_loaded: + self.skipTest( + "torch.classes._TorchScriptTesting._ReLUClass is registered, skipping" + ) diff --git a/misc/py-pytorch/files/patch-test_test__jit.py b/misc/py-pytorch/files/patch-test_test__jit.py new file mode 100644 index 000000000000..ccb3b8585f70 --- /dev/null +++ b/misc/py-pytorch/files/patch-test_test__jit.py @@ -0,0 +1,35 @@ +--- test/test_jit.py.orig 2026-04-18 22:16:10 UTC ++++ test/test_jit.py +@@ -375,6 +375,10 @@ class TestJitProfiler(JitTestCase): + self.graph_executor_optimize_opt + ) + ++ @unittest.skipIf( ++ sys.platform.startswith("freebsd"), ++ "Hangs on FreeBSD due to profiler/JIT interaction deadlock", ++ ) + def test_profiler(self): + torch._C._set_graph_executor_optimize(False) + +@@ -1832,6 +1836,10 @@ graph(%Ra, %Rb): + + @slowTest + @unittest.skipIf(GRAPH_EXECUTOR != ProfilingMode.LEGACY, 'Testing differentiable graph') ++ @unittest.skipIf( ++ GRAPH_EXECUTOR == ProfilingMode.LEGACY, ++ "Hangs in legacy executor mode due to profiler/JIT interaction", ++ ) + def test_dropout_module_requires_grad(self): + with enable_profiling_mode_for_profiling_tests(): + class MyModule(torch.nn.Module): +@@ -1875,6 +1883,10 @@ graph(%Ra, %Rb): + + @unittest.skipIf(GRAPH_EXECUTOR == ProfilingMode.SIMPLE, 'Testing differentiable graph') + @skipIfTorchDynamo("Torchdynamo cannot correctly handle profiler.profile calls") ++ @unittest.skipIf( ++ sys.platform.startswith("freebsd"), ++ "Hangs on FreeBSD due to profiler/JIT interaction deadlock", ++ ) + def test_dropout_func_requires_grad(self): + def dropout_training(input): + return F.dropout(input, 0.5, training=True) diff --git a/misc/py-pytorch/files/patch-test_test__jit__profiling.py b/misc/py-pytorch/files/patch-test_test__jit__profiling.py new file mode 100644 index 000000000000..1bd0d3e409ee --- /dev/null +++ b/misc/py-pytorch/files/patch-test_test__jit__profiling.py @@ -0,0 +1,16 @@ +--- test/test_jit_profiling.py.orig 2026-04-18 23:58:15 UTC ++++ test/test_jit_profiling.py +@@ -2,6 +2,13 @@ sys.argv.append("--jit-executor=profiling") + + import sys + sys.argv.append("--jit-executor=profiling") ++from torch.testing._internal.common_utils import parse_cmd_line_args, run_tests # noqa: F401 ++ ++if __name__ == '__main__': ++ # The value of GRAPH_EXECUTOR depends on command line arguments so make sure they're parsed ++ # before instantiating tests. ++ parse_cmd_line_args() ++ + from test_jit import * # noqa: F403 + + if __name__ == '__main__': diff --git a/misc/py-pytorch/files/patch-test_test__multiprocessing.py b/misc/py-pytorch/files/patch-test_test__multiprocessing.py new file mode 100644 index 000000000000..03b205149cbc --- /dev/null +++ b/misc/py-pytorch/files/patch-test_test__multiprocessing.py @@ -0,0 +1,21 @@ +--- test/test_multiprocessing.py.orig 2026-04-19 00:27:38 UTC ++++ test/test_multiprocessing.py +@@ -33,7 +33,7 @@ TEST_REPEATS = 30 + load_tests = load_tests # noqa: PLW0127 + + TEST_REPEATS = 30 +-HAS_SHM_FILES = os.path.isdir("/dev/shm") ++HAS_SHM_FILES = os.path.isdir("/dev/shm") and not sys.platform.startswith("freebsd") + MAX_WAITING_TIME_IN_SECONDS = 30 + + TEST_CUDA_IPC = ( +@@ -497,7 +497,8 @@ class TestMultiprocessing(TestCase): + simple_autograd_function() + # Autograd only uses thread when GPUs are involved + if ( +- torch.cuda.is_available() ++ sys.platform.startswith("freebsd") ++ or torch.cuda.is_available() + or torch.backends.mps.is_available() + or torch.xpu.is_available() + ): diff --git a/misc/py-pytorch/files/patch-test_test__torch.py b/misc/py-pytorch/files/patch-test_test__torch.py new file mode 100644 index 000000000000..208fbbcbe079 --- /dev/null +++ b/misc/py-pytorch/files/patch-test_test__torch.py @@ -0,0 +1,12 @@ +--- test/test_torch.py.orig 2026-04-19 01:42:54 UTC ++++ test/test_torch.py +@@ -9464,7 +9464,8 @@ tensor([[[1.+1.j, 1.+1.j, 1.+1.j, ..., 1.+1.j, 1.+1.j + torch.backends.quantized.engine = qe + if torch.backends.quantized.engine != qe: + raise AssertionError(f"qengine not set successfully: expected {qe}, got {torch.backends.quantized.engine}") +- torch.backends.quantized.engine = original_qe ++ if original_qe in qengines: ++ torch.backends.quantized.engine = original_qe + + def test_terminate_handler_on_crash(self): + cmd = [sys.executable, '-c', "import os; os.environ[\"TORCH_CUSTOM_TERMINATE\"] ='1'; \ diff --git a/misc/py-pytorch/files/patch-torch___inductor_compile__worker_____main____.py b/misc/py-pytorch/files/patch-torch___inductor_compile__worker_____main____.py new file mode 100644 index 000000000000..115e1cf1fd23 --- /dev/null +++ b/misc/py-pytorch/files/patch-torch___inductor_compile__worker_____main____.py @@ -0,0 +1,11 @@ +--- torch/_inductor/compile_worker/__main__.py.orig 2026-04-19 02:49:11 UTC ++++ torch/_inductor/compile_worker/__main__.py +@@ -30,7 +30,7 @@ try: + import triton + + assert triton is not None # preload in parent +-except ImportError: ++except (ImportError, AttributeError): + pass + + diff --git a/misc/py-pytorch/files/patch-torch___inductor_cpp__builder.py b/misc/py-pytorch/files/patch-torch___inductor_cpp__builder.py new file mode 100644 index 000000000000..7ac2d5428b6b --- /dev/null +++ b/misc/py-pytorch/files/patch-torch___inductor_cpp__builder.py @@ -0,0 +1,13 @@ +--- torch/_inductor/cpp_builder.py.orig 2026-04-18 06:34:35 UTC ++++ torch/_inductor/cpp_builder.py +@@ -1185,6 +1185,10 @@ def _get_torch_related_args( + if _IS_WINDOWS: + libraries.append("sleef") + ++ if sys.platform.startswith("freebsd"): ++ include_dirs.append("/usr/local/include") ++ libraries.append("sleef") ++ + return include_dirs, libraries_dirs, libraries + + diff --git a/misc/py-pytorch/files/patch-torch___inductor_cpu__vec__isa.py b/misc/py-pytorch/files/patch-torch___inductor_cpu__vec__isa.py new file mode 100644 index 000000000000..df68e32921ee --- /dev/null +++ b/misc/py-pytorch/files/patch-torch___inductor_cpu__vec__isa.py @@ -0,0 +1,31 @@ +--- torch/_inductor/cpu_vec_isa.py.orig 2026-04-18 06:29:09 UTC ++++ torch/_inductor/cpu_vec_isa.py +@@ -438,7 +438,7 @@ def x86_isa_checker() -> list[str]: + """ + Arch value is x86_64 on Linux, and the value is AMD64 on Windows. + """ +- if Arch != "x86_64" and Arch != "AMD64": ++ if Arch != "x86_64" and Arch != "AMD64" and Arch != "amd64": + return supported_isa + + avx2 = torch.cpu._is_avx2_supported() +@@ -504,7 +504,9 @@ def valid_vec_isa_list() -> list[VecISA]: + if sys.platform == "darwin" and platform.processor() == "arm": + isa_list.append(VecNEON()) + +- if sys.platform not in ["linux", "win32"]: ++ if sys.platform not in ["linux", "win32"] and not sys.platform.startswith( ++ "freebsd" ++ ): + return isa_list + + arch = platform.machine() +@@ -529,7 +531,7 @@ def valid_vec_isa_list() -> list[VecISA]: + else: + isa_list.append(VecNEON()) + +- elif arch in ["x86_64", "AMD64"]: ++ elif arch in ["x86_64", "AMD64", "amd64"]: + """ + arch value is x86_64 on Linux, and the value is AMD64 on Windows. + """ diff --git a/misc/py-pytorch/files/patch-torch___inductor_ir.py b/misc/py-pytorch/files/patch-torch___inductor_ir.py new file mode 100644 index 000000000000..f92c7880bb61 --- /dev/null +++ b/misc/py-pytorch/files/patch-torch___inductor_ir.py @@ -0,0 +1,11 @@ +--- torch/_inductor/ir.py.orig 2026-04-19 02:49:11 UTC ++++ torch/_inductor/ir.py +@@ -133,7 +133,7 @@ try: + + triton_version = triton.__version__ + has_triton = True +-except ImportError: ++except (ImportError, AttributeError): + triton_version = None + has_triton = False + diff --git a/misc/py-pytorch/files/patch-torch___inductor_kernel_mm.py b/misc/py-pytorch/files/patch-torch___inductor_kernel_mm.py new file mode 100644 index 000000000000..bb49e34c8678 --- /dev/null +++ b/misc/py-pytorch/files/patch-torch___inductor_kernel_mm.py @@ -0,0 +1,11 @@ +--- torch/_inductor/kernel/mm.py.orig 2026-04-19 02:49:11 UTC ++++ torch/_inductor/kernel/mm.py +@@ -70,7 +70,7 @@ try: + + triton_version = TorchVersion(triton.__version__) + has_triton = True +-except ImportError: ++except (ImportError, AttributeError): + triton_version = TorchVersion("0.0.0") + has_triton = False + diff --git a/misc/py-pytorch/files/patch-torch___inductor_runtime_triton__compat.py b/misc/py-pytorch/files/patch-torch___inductor_runtime_triton__compat.py new file mode 100644 index 000000000000..3d2d9a445daa --- /dev/null +++ b/misc/py-pytorch/files/patch-torch___inductor_runtime_triton__compat.py @@ -0,0 +1,12 @@ +--- torch/_inductor/runtime/triton_compat.py.orig 2026-04-19 02:47:11 UTC ++++ torch/_inductor/runtime/triton_compat.py +@@ -8,7 +8,8 @@ try: + + try: + import triton +-except ImportError: ++ import triton.language # Verify it's a real install, not a namespace package ++except (ImportError, AttributeError): + triton = None + + diff --git a/misc/py-pytorch/files/patch-torch___utils__internal.py b/misc/py-pytorch/files/patch-torch___utils__internal.py new file mode 100644 index 000000000000..66f6922f397e --- /dev/null +++ b/misc/py-pytorch/files/patch-torch___utils__internal.py @@ -0,0 +1,14 @@ +--- torch/_utils_internal.py.orig 2026-04-18 15:44:50 UTC ++++ torch/_utils_internal.py +@@ -265,7 +265,10 @@ USE_GLOBAL_DEPS = True + USE_GLOBAL_DEPS = True + # USE_RTLD_GLOBAL_WITH_LIBTORCH controls whether __init__.py tries to load + # _C.so with RTLD_GLOBAL during the call to dlopen. +-USE_RTLD_GLOBAL_WITH_LIBTORCH = False ++# On FreeBSD, we need RTLD_GLOBAL to ensure weak RTTI typeinfo symbols (e.g. ++# c10::TypeError) are shared across DSO boundaries, enabling correct C++ ++# exception translation in JIT-compiled extensions. ++USE_RTLD_GLOBAL_WITH_LIBTORCH = sys.platform.startswith("freebsd") + # If an op was defined in C++ and extended from Python using the + # torch.library.register_fake, returns if we require that there be a + # m.set_python_module("mylib.ops") call from C++ that associates diff --git a/misc/py-pytorch/files/patch-torch_csrc_Exceptions.cpp b/misc/py-pytorch/files/patch-torch_csrc_Exceptions.cpp new file mode 100644 index 000000000000..7f30185538ea --- /dev/null +++ b/misc/py-pytorch/files/patch-torch_csrc_Exceptions.cpp @@ -0,0 +1,34 @@ +--- torch/csrc/Exceptions.cpp.orig 2026-04-18 16:00:24 UTC ++++ torch/csrc/Exceptions.cpp +@@ -11,6 +11,31 @@ + + #include <c10/util/StringUtil.h> + ++// Out-of-line definitions for python_error, PyTorchError, TypeError, AttributeError. ++// These establish key functions so that vtables/typeinfo are emitted only here ++// (in libtorch_python.so) and exported with default visibility, enabling ++// correct cross-DSO RTTI matching on FreeBSD and other ELF platforms. ++python_error::~python_error() { ++ if (type || value || traceback) { ++ pybind11::gil_scoped_acquire gil; ++ Py_XDECREF(type); ++ Py_XDECREF(value); ++ Py_XDECREF(traceback); ++ } ++} ++const char* python_error::what() const noexcept { ++ return message.c_str(); ++} ++const char* torch::PyTorchError::what() const noexcept { ++ return msg.c_str(); ++} ++PyObject* torch::TypeError::python_type() { ++ return PyExc_TypeError; ++} ++PyObject* torch::AttributeError::python_type() { ++ return PyExc_AttributeError; ++} ++ + PyObject *THPException_FatalError, *THPException_LinAlgError, + *THPException_OutOfMemoryError, *THPException_DistError, + *THPException_DistBackendError, *THPException_DistNetworkError, diff --git a/misc/py-pytorch/files/patch-torch_csrc_Exceptions.h b/misc/py-pytorch/files/patch-torch_csrc_Exceptions.h new file mode 100644 index 000000000000..3b6601ffdbfc --- /dev/null +++ b/misc/py-pytorch/files/patch-torch_csrc_Exceptions.h @@ -0,0 +1,86 @@ +--- torch/csrc/Exceptions.h.orig 2026-04-18 16:00:24 UTC ++++ torch/csrc/Exceptions.h +@@ -153,7 +153,10 @@ extern PyObject *THPException_FatalError, *THPExceptio + + // Throwing this exception means that the python error flags have been already + // set and control should be immediately returned to the interpreter. +-struct python_error : public std::exception { ++// TORCH_PYTHON_API on the struct gives vtable/typeinfo default visibility so ++// they are exported from libtorch_python.so and can be matched across DSOs ++// (critical for FreeBSD libcxxrt which uses pointer-only RTTI comparison). ++struct TORCH_PYTHON_API python_error : public std::exception { + python_error() = default; + + python_error(const python_error& other) +@@ -181,18 +184,12 @@ struct python_error : public std::exception { + python_error& operator=(python_error&& other) = delete; + + // NOLINTNEXTLINE(bugprone-exception-escape) +- ~python_error() override { +- if (type || value || traceback) { +- pybind11::gil_scoped_acquire gil; +- Py_XDECREF(type); +- Py_XDECREF(value); +- Py_XDECREF(traceback); +- } +- } ++ // Non-inline: establishes key function so typeinfo is emitted only in ++ // Exceptions.cpp (with default visibility), enabling cross-DSO RTTI. ++ ~python_error() override; + +- const char* what() const noexcept override { +- return message.c_str(); +- } ++ // Non-inline for the same reason as ~python_error(). ++ const char* what() const noexcept override; + + void build_message() { + // Ensure we have the GIL. +@@ -274,34 +271,31 @@ TORCH_PYTHON_API std::string processErrorMsg(std::stri + + TORCH_PYTHON_API std::string processErrorMsg(std::string str); + +-// Abstract base class for exceptions which translate to specific Python types +-struct PyTorchError : public std::exception { ++// Abstract base class for exceptions which translate to specific Python types. ++// TORCH_PYTHON_API on the struct gives vtable/typeinfo default visibility so ++// they are exported from libtorch_python.so and can be matched across DSOs. ++struct TORCH_PYTHON_API PyTorchError : public std::exception { + PyTorchError() = default; + PyTorchError(std::string msg_) : msg(std::move(msg_)) {} + virtual PyObject* python_type() = 0; +- const char* what() const noexcept override { +- return msg.c_str(); +- } ++ // Defined out-of-line to establish a key function. ++ const char* what() const noexcept override; + std::string msg; + }; + + // Translates to Python TypeError +-struct TypeError : public PyTorchError { +- TORCH_PYTHON_API TypeError() = default; +- TORCH_PYTHON_API TypeError(std::string msg_) +- : PyTorchError(std::move(msg_)) {} ++struct TORCH_PYTHON_API TypeError : public PyTorchError { ++ TypeError() = default; ++ TypeError(std::string msg_) : PyTorchError(std::move(msg_)) {} + using PyTorchError::PyTorchError; +- PyObject* python_type() override { +- return PyExc_TypeError; +- } ++ // Out-of-line to give TypeError its own key function for RTTI export. ++ PyObject* python_type() override; + }; + + // Translates to Python AttributeError +-struct AttributeError : public PyTorchError { ++struct TORCH_PYTHON_API AttributeError : public PyTorchError { + using PyTorchError::PyTorchError; +- PyObject* python_type() override { +- return PyExc_AttributeError; +- } ++ PyObject* python_type() override; + }; + + // ATen warning handler for Python diff --git a/misc/py-pytorch/files/patch-torch_csrc_jit_ir_attributes.h b/misc/py-pytorch/files/patch-torch_csrc_jit_ir_attributes.h new file mode 100644 index 000000000000..26563e9add33 --- /dev/null +++ b/misc/py-pytorch/files/patch-torch_csrc_jit_ir_attributes.h @@ -0,0 +1,36 @@ +--- torch/csrc/jit/ir/attributes.h.orig 2026-04-18 20:22:08 UTC ++++ torch/csrc/jit/ir/attributes.h +@@ -66,6 +66,9 @@ struct ScalarAttributeValue : public AttributeValue { + struct ScalarAttributeValue : public AttributeValue { + using ConstructorType = T; + using ValueType = T; ++ // kAttrKind lets getAttr<T> verify the runtime kind without dynamic_cast, ++ // working around FreeBSD libcxxrt pointer-based RTTI across DSO boundaries. ++ static constexpr AttributeKind kAttrKind = Kind; + ScalarAttributeValue(Symbol name, ConstructorType value_) + : AttributeValue(name), value_(std::move(value_)) {} + ValueType& value() { +@@ -86,6 +89,7 @@ struct VectorAttributeValue : public AttributeValue { + struct VectorAttributeValue : public AttributeValue { + using ConstructorType = std::vector<T>; + using ValueType = std::vector<T>; ++ static constexpr AttributeKind kAttrKind = Kind; + VectorAttributeValue(Symbol name, ConstructorType value_) + : AttributeValue(name), value_(std::move(value_)) {} + ValueType& value() { +@@ -126,6 +130,7 @@ struct TORCH_API GraphAttr : public AttributeValue { + struct TORCH_API GraphAttr : public AttributeValue { + using ConstructorType = std::shared_ptr<Graph>; + using ValueType = std::shared_ptr<Graph>; ++ static constexpr AttributeKind kAttrKind = AttributeKind::g; + GraphAttr(Symbol name, ConstructorType value_) + : AttributeValue(name), value_(std::move(value_)) {} + ValueType& value() { +@@ -143,6 +148,7 @@ struct TORCH_API GraphsAttr : public AttributeValue { + struct TORCH_API GraphsAttr : public AttributeValue { + using ConstructorType = std::vector<std::shared_ptr<Graph>>; + using ValueType = std::vector<std::shared_ptr<Graph>>; ++ static constexpr AttributeKind kAttrKind = AttributeKind::gs; + GraphsAttr(Symbol name, ConstructorType value_) + : AttributeValue(name), value_(std::move(value_)) {} + ValueType& value() { diff --git a/misc/py-pytorch/files/patch-torch_csrc_jit_ir_ir.h b/misc/py-pytorch/files/patch-torch_csrc_jit_ir_ir.h new file mode 100644 index 000000000000..624e3c52dbc2 --- /dev/null +++ b/misc/py-pytorch/files/patch-torch_csrc_jit_ir_ir.h @@ -0,0 +1,26 @@ +--- torch/csrc/jit/ir/ir.h.orig 2026-04-18 03:53:37 UTC ++++ torch/csrc/jit/ir/ir.h +@@ -943,11 +943,22 @@ struct TORCH_API Node { + typename T::ValueType& getAttr(Symbol name) const { + AT_ASSERT(name.is_attr()); + auto it = findAttr(name, true); +- auto* child = dynamic_cast<T*>(it->get()); ++ auto* base = it->get(); ++#if defined(__FreeBSD__) ++ // FreeBSD's libcxxrt uses pointer-based typeinfo comparison; dynamic_cast ++ // across DSO boundaries fails for template specialisations whose typeinfo ++ // symbol is HIDDEN (not exported). Use kind() + static_cast instead. ++ if (base->kind() != T::kAttrKind) { ++ throw IRAttributeError(name, true); ++ } ++ return static_cast<T*>(base)->value(); ++#else ++ auto* child = dynamic_cast<T*>(base); + if (child == nullptr) { + throw IRAttributeError(name, true); + } + return child->value(); ++#endif + } + using AVPtr = AttributeValue::Ptr; + // NB: For determinism, we use a vector rather than a hash map. This does diff --git a/misc/py-pytorch/files/patch-torch_csrc_jit_passes_inplace__check.cpp b/misc/py-pytorch/files/patch-torch_csrc_jit_passes_inplace__check.cpp new file mode 100644 index 000000000000..cd2b0094b85d --- /dev/null +++ b/misc/py-pytorch/files/patch-torch_csrc_jit_passes_inplace__check.cpp @@ -0,0 +1,21 @@ +--- torch/csrc/jit/passes/inplace_check.cpp.orig 2026-04-18 04:20:00 UTC ++++ torch/csrc/jit/passes/inplace_check.cpp +@@ -7,8 +7,17 @@ static void CheckInplace(Block* block) { + static void CheckInplace(Block* block) { + for (auto node : block->nodes()) { + if (node->kind() == prim::PythonOp && node->hasAttribute(attr::inplace)) { ++ // On FreeBSD, ScalarAttributeValue<T> typeinfo symbols are local to each ++ // DSO (no exported key function), so dynamic_cast across DSO boundaries ++ // (from python to cpu library) may fail. Guard with try/catch. ++ bool is_inplace = false; ++ try { ++ is_inplace = (bool)node->i(attr::inplace); ++ } catch (const std::exception&) { ++ // Cannot determine; treat as not-inplace (conservative safe default). ++ } + TORCH_CHECK( +- !node->i(attr::inplace), ++ !is_inplace, + "inplace ", + static_cast<PythonOp*>(node)->name(), + " not supported in the JIT"); diff --git a/misc/py-pytorch/files/patch-torch_distributed_elastic_multiprocessing_redirects.py b/misc/py-pytorch/files/patch-torch_distributed_elastic_multiprocessing_redirects.py new file mode 100644 index 000000000000..7982c51cfd73 --- /dev/null +++ b/misc/py-pytorch/files/patch-torch_distributed_elastic_multiprocessing_redirects.py @@ -0,0 +1,13 @@ +--- torch/distributed/elastic/multiprocessing/redirects.py.orig 2026-04-19 02:32:30 UTC ++++ torch/distributed/elastic/multiprocessing/redirects.py +@@ -31,7 +31,9 @@ def get_libc(): + ) + return None + else: +- return ctypes.CDLL("libc.so.6") ++ import ctypes.util ++ libc_name = ctypes.util.find_library("c") or "libc.so.6" ++ return ctypes.CDLL(libc_name) + + + libc = get_libc() diff --git a/misc/py-pytorch/files/patch-torch_jit___trace.py b/misc/py-pytorch/files/patch-torch_jit___trace.py index 5415c1466564..a34e198af2a1 100644 --- a/misc/py-pytorch/files/patch-torch_jit___trace.py +++ b/misc/py-pytorch/files/patch-torch_jit___trace.py @@ -1,6 +1,59 @@ --- torch/jit/_trace.py.orig 2026-04-18 00:49:58 UTC +++ torch/jit/_trace.py -@@ -445,8 +445,11 @@ def _check_trace( +@@ -300,6 +300,13 @@ def indent(s): + return "\n".join(["\t" + line for line in s.splitlines()]) + + ++def _safe_str(x): ++ try: ++ return str(x) ++ except RuntimeError: ++ return "<str() failed>" ++ ++ + class TracingCheckError(Exception): + def __init__(self, graph_diff_error, tensor_compare_error, extra_msg=None): + self.message = "Tracing failed sanity checks!\n" +@@ -387,12 +394,18 @@ def _check_trace( + mod_canonicalized = torch._C._jit_pass_canonicalize(traced_func.graph) + torch._C._jit_pass_inline(mod_canonicalized) + torch._C._jit_pass_erase_shape_information(mod_canonicalized) +- mod_str = str(mod_canonicalized) ++ try: ++ mod_str = str(mod_canonicalized) ++ except RuntimeError: ++ mod_str = "" + mod_str = re.sub(r"___torch_mangle_[0-9]+\.", "", mod_str) + check_canonicalized = torch._C._jit_pass_canonicalize(check_mod_func.graph) + torch._C._jit_pass_inline(check_canonicalized) + torch._C._jit_pass_erase_shape_information(check_canonicalized) +- check_str = str(check_canonicalized) ++ try: ++ check_str = str(check_canonicalized) ++ except RuntimeError: ++ check_str = "" + check_str = re.sub(r"___torch_mangle_[0-9]+\.", "", check_str) + + graph_diff_errors = None +@@ -407,10 +420,15 @@ def _check_trace( + for n_mod, n_check in zip( + mod_canonicalized.nodes(), check_canonicalized.nodes() + ): +- if str(n_mod) != str(n_check): ++ try: ++ n_mod_str = str(n_mod) ++ n_check_str = str(n_check) ++ except RuntimeError: *** 109 LINES SKIPPED ***home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69e7c889.19566.45f7dde6>
