Skip to content

Commit d5b5a92

Browse files
committed
Pin the CUDA fallback kernel the backend just started advertising
The CUDA test that asserts the exact set of fallback kernels fails: test_cuda_fallbacks_unchanged_by_rocm_gate An earlier commit taught the backend to accept the shim spelling Inductor now derives for the int4 pack matmul, but this test compares the advertised set against a frozen copy of it, so adding an entry on one side alone breaks the comparison. Add the same entry here. The Metal backend took the same kind of change and is unaffected, because nothing pins its set exactly. Test Plan: Extracted both sets and compared them directly. Before this the advertised set has twelve entries and the frozen copy eleven, with the new derived spelling the only difference and nothing frozen that the backend no longer advertises, so the comparison fails on exactly that one name. After, both hold twelve and the comparison passes. Treat a test that names c10 as an ATen test too The Buck test targets decide their C++ standard separately from the libraries, and their check for "is this an ATen test" looks for a dependency named `libtorch` but not for the other two names the build maps onto the same library. A test that names `c10` or `torch-core-cpp` was therefore pinned to C++17 and failed on ATen's headers, which need C++20 as of PyTorch 2.14: ATen/core/TensorBase.h: error: expected ';' at end of declaration Reuse the same check the library path already uses, so both paths agree on what counts as ATen. It covers all three dependency names, and the exported list as well as the plain one. The rest of the test check is left alone: a name containing `aten`, and the ATen flavours of the test framework, still mark a test as ATen on their own. Test Plan: Ran the wrapper function directly, with `type()` behaving as Starlark's does, over the cases that matter. Before this a test naming `c10` or `torch-core-cpp` came back with C++17; after, both come back without a pin and take C++20 from the toolchain. A plain test with no ATen dependency still comes back with C++17, which is the case the embedded build depends on, and a test named for ATen or naming `libtorch` is unchanged. Moved the shared check above its first use, since it now has one earlier in the file, and dropped a local that nothing reads any more. Put the C++20 flag where the compiler actually reads it The Buck build still fails compiling anything generated that includes ATen: ATen/core/TensorBase.h:1031:5: error: unknown type name 'requires' `requires` is a C++20 keyword, so the compile was still running at C++17 even though the target is ATen-mode and the wrapper had already decided it should be C++20. The wrapper was setting the standard only in the per-language flags, which reach the preprocessor pass. That was enough while the value matched the build config, which pins C++17 for everything, and it is not enough to override it. Set the flag on the target's own compile flags as well, for ATen-mode targets only. Nothing changes for the rest of the build: a target that is not ATen-mode gets no flag added here and keeps the C++17 the build config gives it. Test Plan: Ran the wrapper over the exact arguments the generated kernel library is defined with, the ones from the failure. Before this it came away with only its own warning flag and the standard confined to the per-language entry, which is why the compile stayed at C++17. After, the flag is on the target's own list where the compile reads it. Checked the case that must not move: a library with no ATen dependency still gets C++17 and no flag on its own list. Confirmed why the old spelling looked sufficient. It only ever carried C++17, matching the build config, so nothing had shown it could raise a standard rather than restate one. I cannot run this Buck build on this machine, so CI has to confirm the generated libraries now compile. Raise the ATen-mode C++ standard where both builds see it The C++20 flag for ATen-mode targets was set in the interface layer that exists only for the open source build, whose own docstring says as much. So the internal build never got it, and the shared wrapper was passing that layer an argument its internal counterpart does not accept, which would fail there rather than being merely ineffective. Move the decision into the shared wrapper, which both builds go through, and leave the interface layer exactly as it was. The flag goes on the target's own compile flags, because the build config applies C++17 to everything and only a flag on the target overrides it. Test Plan: Read the two files' own descriptions of themselves to place this: the interface layer is for changes specific to one build, the wrapper is for logic shared with the internal one. Confirmed the internal counterpart takes only the arguments it always took, so the previous version would have broken it rather than skipped it. Ran the new helper over the target from the failure and over targets that must not move. The generated kernel library and the ATen bridge come away with C++20; a plain library and the portable kernels come away with no flag added, so they keep the C++17 the build config gives them, which is what the embedded builds rely on. I cannot run either Buck build here, so CI has to confirm the generated libraries compile. Decide ATen mode before the wrapper consumes the dependency list The Buck build still failed compiling generated sources that include ATen: ATen/core/TensorBase.h:1031:5: error: unknown type name 'requires' The check for "is this an ATen target" reads the external dependency list, but by the time it ran, an earlier step in the same wrapper had already removed that list after turning its entries into real dependencies. So every target looked like a non-ATen one, no target was ever raised to C++20, and the flag added for it was never added at all. Read the list first, then let the rest of the wrapper consume it. Test Plan: Traced the order in the wrapper: the step that removes the list runs before the step that read it. Reproduced that by running both against the target from the failure: it reports ATen mode with the list present and not once it is gone, which is exactly the sequence the wrapper produced. Reran the whole path in the new order over the target from the failure, an ATen target that exports its dependency instead of naming it directly, and a plain library. The first two now come away at C++20 and the plain one is untouched, so the embedded builds keep the C++17 they rely on. Also read the build system's own source to confirm the flag can win where it is placed: a target's flags are appended after the toolchain's, and its comment says they are last on purpose. So the earlier concern that the flag was being placed somewhere that could not take effect was unfounded; it simply was not being added. Shortened an overlong comment that failed the formatter. I cannot run this Buck build here, so CI has to confirm the generated libraries compile.
1 parent 8d79988 commit d5b5a92

4 files changed

Lines changed: 34 additions & 29 deletions

File tree

‎backends/aoti/common_shims.h‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ aoti_torch_get_dim(Tensor* tensor, int64_t* ret_dim);
6262
AOTI_SHIM_EXPORT AOTITorchError
6363
aoti_torch_get_numel(Tensor* tensor, int64_t* ret_numel);
6464

65-
// Reports whether the handle refers to a real tensor. PyTorch has an undefined
66-
// tensor state that ExecuTorch has no equivalent for, so this is a null check.
65+
// PyTorch has an undefined-tensor state with no equivalent here: null check.
6766
AOTI_SHIM_EXPORT AOTITorchError
6867
aoti_torch_is_defined(Tensor* tensor, bool* ret_is_defined);
6968

‎backends/cuda/tests/test_sort_shim.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
_CUDA_FALLBACK_KERNELS = frozenset(
3838
{
3939
"at::_ops::_weight_int4pack_mm::call",
40+
"aoti_torch_cuda__weight_int4pack_mm",
4041
"at::_ops::sort_stable::call",
4142
"aoti_torch_cuda_randint_low_out",
4243
"executorch_cuda::int4_plain_mm",

‎shim_et/xplat/executorch/build/env_interface.bzl‎

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -160,21 +160,14 @@ def _patch_headers(kwargs):
160160
def _patch_pp_flags(kwargs):
161161
return kwargs
162162

163-
def _patch_cxx_compiler_flags(kwargs, aten_mode = False):
164-
"""Pins the C++ standard a target compiles with.
165-
166-
C++17 by default, which is what the runtime this project ships requires.
167-
ATen-mode targets are raised to C++20, because PyTorch's headers require it as
168-
of 2.14: c10/util/intrusive_ptr.h defines operator<=> and returns
169-
std::strong_ordering with no feature guard.
170-
"""
171-
std = "-std=c++20" if aten_mode else "-std=c++17"
163+
def _patch_cxx_compiler_flags(kwargs):
164+
"""CXX Compiler flags to enable C++17 features."""
172165
if "lang_compiler_flags" not in kwargs:
173-
kwargs["lang_compiler_flags"] = {"cxx_cpp_output": [std]}
166+
kwargs["lang_compiler_flags"] = {"cxx_cpp_output": ["-std=c++17"]}
174167
elif "cxx_cpp_output" not in kwargs["lang_compiler_flags"]:
175-
kwargs["lang_compiler_flags"]["cxx_cpp_output"] = [std]
168+
kwargs["lang_compiler_flags"]["cxx_cpp_output"] = ["-std=c++17"]
176169
else:
177-
kwargs["lang_compiler_flags"]["cxx_cpp_output"].append(std)
170+
kwargs["lang_compiler_flags"]["cxx_cpp_output"].append("-std=c++17")
178171
return kwargs
179172

180173
# buildifier: disable=unused-variable

‎shim_et/xplat/executorch/build/runtime_wrapper.bzl‎

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,18 @@ def _has_pytorch_dep(dep_list):
145145
return True
146146
return False
147147

148+
def _is_aten_target(kwargs):
149+
"""Whether a target compiles against ATen.
150+
151+
Keyed on exact dep names, not a substring: every label contains "torch".
152+
"""
153+
aten_external_deps = ["c10", "libtorch", "libtorch_python", "torch-core-cpp"]
154+
for key in ["external_deps", "exported_external_deps"]:
155+
for dep in kwargs.get(key) or []:
156+
if dep in aten_external_deps:
157+
return True
158+
return False
159+
148160
def _patch_test_compiler_flags(kwargs):
149161
if "compiler_flags" not in kwargs:
150162
kwargs["compiler_flags"] = []
@@ -154,16 +166,14 @@ def _patch_test_compiler_flags(kwargs):
154166
# non-aten tests are pinned to C++17 for embedded.
155167
name = kwargs.get("name", "")
156168
external_deps = kwargs.get("external_deps", [])
157-
deps = kwargs.get("deps", [])
158169
xplat_deps = kwargs.get("xplat_deps", [])
159170
fbcode_deps = kwargs.get("fbcode_deps", [])
160171
is_aten_test = (
161172
"_aten" in name or
162173
"aten_" in name or
163-
"libtorch" in external_deps or
164174
"gtest_aten" in external_deps or
165175
"gmock_aten" in external_deps or
166-
_has_pytorch_dep(deps) or
176+
_is_aten_target(kwargs) or
167177
_has_pytorch_dep(xplat_deps) or
168178
_has_pytorch_dep(fbcode_deps)
169179
)
@@ -267,27 +277,26 @@ def _patch_kwargs_cxx(kwargs):
267277
env.remove_platform_specific_args(kwargs)
268278
return _patch_kwargs_common(kwargs)
269279

270-
def _is_aten_target(kwargs):
271-
"""Whether a target compiles against ATen, and so needs C++20.
280+
def _patch_aten_mode_std(kwargs, aten_mode):
281+
"""Raises an ATen-mode target to C++20, which PyTorch's headers require.
272282
273-
Keyed on the external dep names the build maps onto libtorch, rather than on
274-
a substring of the label: every ExecuTorch label contains "torch".
283+
A plain compiler flag, which the prelude places after the toolchain's.
275284
"""
276-
aten_external_deps = ["c10", "libtorch", "libtorch_python", "torch-core-cpp"]
277-
for key in ["external_deps", "exported_external_deps"]:
278-
for dep in kwargs.get(key) or []:
279-
if dep in aten_external_deps:
280-
return True
281-
return False
285+
if aten_mode:
286+
kwargs["compiler_flags"] = kwargs.get("compiler_flags", []) + ["-std=c++20"]
287+
return kwargs
282288

283289
def _cxx_library_common(*args, **kwargs):
290+
# Before _patch_kwargs_cxx, which consumes external_deps.
291+
aten_mode = _is_aten_target(kwargs)
284292
_patch_kwargs_cxx(kwargs)
285293
_patch_build_mode_flags(kwargs)
294+
_patch_aten_mode_std(kwargs, aten_mode)
286295

287296
env.patch_platform_build_mode_flags(kwargs)
288297
env.patch_headers(kwargs)
289298
env.patch_pp_flags(kwargs)
290-
env.patch_cxx_compiler_flags(kwargs, aten_mode = _is_aten_target(kwargs))
299+
env.patch_cxx_compiler_flags(kwargs)
291300
env.patch_force_static(kwargs)
292301

293302
env.cxx_library(*args, **kwargs)
@@ -307,10 +316,13 @@ def _cxx_library(*args, **kwargs):
307316
_cxx_library_common(*args, **kwargs)
308317

309318
def _cxx_binary_helper(*args, **kwargs):
319+
# Before _patch_kwargs_cxx, which consumes external_deps.
320+
aten_mode = _is_aten_target(kwargs)
310321
_patch_kwargs_cxx(kwargs)
311322
_patch_build_mode_flags(kwargs)
323+
_patch_aten_mode_std(kwargs, aten_mode)
312324
env.patch_platform_build_mode_flags(kwargs)
313-
env.patch_cxx_compiler_flags(kwargs, aten_mode = _is_aten_target(kwargs))
325+
env.patch_cxx_compiler_flags(kwargs)
314326

315327
env.cxx_binary(*args, **kwargs)
316328

0 commit comments

Comments
 (0)