From 901b57eb63b8a93f3561aa17559619da55c1bd93 Mon Sep 17 00:00:00 2001 From: Roman Cattaneo Date: Fri, 8 May 2026 19:54:50 +0200 Subject: [PATCH 1/7] fix[cartesian]: log10 percision issue `log10(x)` will always be in double precision, regardless of `GT4PY_LITERAL_FLOAT_PRECISION`. With this PR, we are deferring to `dace.math.log10`, which is a templated version that respects the floating point precision. --- .../cartesian/gtc/dace/oir_to_tasklet.py | 2 +- .../test_gtc/dace/test_oir_to_tasklet.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/gt4py/cartesian/gtc/dace/oir_to_tasklet.py b/src/gt4py/cartesian/gtc/dace/oir_to_tasklet.py index 2329128d70..3cad8aab08 100644 --- a/src/gt4py/cartesian/gtc/dace/oir_to_tasklet.py +++ b/src/gt4py/cartesian/gtc/dace/oir_to_tasklet.py @@ -243,7 +243,7 @@ def visit_NativeFunction(self, node: common.NativeFunction, **_kwargs: Any) -> s common.NativeFunction.POW: "dace.math.pow", common.NativeFunction.EXP: "dace.math.exp", common.NativeFunction.LOG: "dace.math.log", - common.NativeFunction.LOG10: "log10", + common.NativeFunction.LOG10: "dace.math.log10", common.NativeFunction.GAMMA: "tgamma", common.NativeFunction.CBRT: "cbrt", common.NativeFunction.ISFINITE: "isfinite", diff --git a/tests/cartesian_tests/unit_tests/test_gtc/dace/test_oir_to_tasklet.py b/tests/cartesian_tests/unit_tests/test_gtc/dace/test_oir_to_tasklet.py index 1ecb7659ee..980727fa3c 100644 --- a/tests/cartesian_tests/unit_tests/test_gtc/dace/test_oir_to_tasklet.py +++ b/tests/cartesian_tests/unit_tests/test_gtc/dace/test_oir_to_tasklet.py @@ -139,3 +139,22 @@ def test_integer_power_of_integer() -> None: tasklet_code = visitor.visit_NativeFuncCall(pow_call, ctx=fake_context, is_target=False) assert "ipow" not in tasklet_code + + +@pytest.mark.parametrize( + "arg", + [ + oir.Literal(value="2", dtype=common.DataType.FLOAT32), + oir.Literal(value="2", dtype=common.DataType.FLOAT64), + ], +) +def test_log10_respects_floating_point_precision(arg: oir.Literal) -> None: + log10_call = oir.NativeFuncCall(func=common.NativeFunction.LOG10, args=[arg]) + + visitor = oir_to_tasklet.OIRToTasklet() + fake_context = oir_to_tasklet.Context( + code="asdf", targets=set(), inputs={}, outputs={}, tree=None, scope=None + ) + tasklet_code = visitor.visit_NativeFuncCall(log10_call, ctx=fake_context, is_target=False) + + assert "dace.math.log10" in tasklet_code From 1abd6c7a9f594cffac47a0c6d605624cf214c314 Mon Sep 17 00:00:00 2001 From: Roman Cattaneo Date: Mon, 11 May 2026 14:37:32 +0200 Subject: [PATCH 2/7] Expose more math functions in `dace/math.h` --- pyproject.toml | 2 +- .../cartesian/gtc/dace/oir_to_tasklet.py | 26 +++++++++---------- uv.lock | 6 ++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e4a5609d93..e6d0a33549 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -485,7 +485,7 @@ url = 'https://gridtools.github.io/pypi/' [tool.uv.sources] atlas4py = {index = "test.pypi"} dace = [ - {git = "https://github.com/GridTools/dace", branch = "romanc/stree-v2", group = "dace-cartesian"}, + {git = "https://github.com/GridTools/dace", branch = "romanc/math-functions", group = "dace-cartesian"}, {index = "gridtools", group = "dace-next"} ] diff --git a/src/gt4py/cartesian/gtc/dace/oir_to_tasklet.py b/src/gt4py/cartesian/gtc/dace/oir_to_tasklet.py index 3cad8aab08..6a7c71047e 100644 --- a/src/gt4py/cartesian/gtc/dace/oir_to_tasklet.py +++ b/src/gt4py/cartesian/gtc/dace/oir_to_tasklet.py @@ -226,38 +226,38 @@ def visit_NativeFunction(self, node: common.NativeFunction, **_kwargs: Any) -> s common.NativeFunction.ABS: "abs", common.NativeFunction.MIN: "min", common.NativeFunction.MAX: "max", - common.NativeFunction.MOD: "fmod", + common.NativeFunction.MOD: "dace.math.fmod", common.NativeFunction.SIN: "dace.math.sin", common.NativeFunction.COS: "dace.math.cos", common.NativeFunction.TAN: "dace.math.tan", - common.NativeFunction.ARCSIN: "asin", - common.NativeFunction.ARCCOS: "acos", - common.NativeFunction.ARCTAN: "atan", + common.NativeFunction.ARCSIN: "dace.math.asin", + common.NativeFunction.ARCCOS: "dace.math.acos", + common.NativeFunction.ARCTAN: "dace.math.atan", common.NativeFunction.SINH: "dace.math.sinh", common.NativeFunction.COSH: "dace.math.cosh", common.NativeFunction.TANH: "dace.math.tanh", - common.NativeFunction.ARCSINH: "asinh", - common.NativeFunction.ARCCOSH: "acosh", - common.NativeFunction.ARCTANH: "atanh", + common.NativeFunction.ARCSINH: "dace.math.asinh", + common.NativeFunction.ARCCOSH: "dace.math.acosh", + common.NativeFunction.ARCTANH: "dace.math.atanh", common.NativeFunction.SQRT: "dace.math.sqrt", common.NativeFunction.POW: "dace.math.pow", common.NativeFunction.EXP: "dace.math.exp", common.NativeFunction.LOG: "dace.math.log", common.NativeFunction.LOG10: "dace.math.log10", - common.NativeFunction.GAMMA: "tgamma", - common.NativeFunction.CBRT: "cbrt", + common.NativeFunction.GAMMA: "dace.math.tgamma", + common.NativeFunction.CBRT: "dace.math.cbrt", common.NativeFunction.ISFINITE: "isfinite", common.NativeFunction.ISINF: "isinf", common.NativeFunction.ISNAN: "isnan", common.NativeFunction.FLOOR: "dace.math.ifloor", - common.NativeFunction.CEIL: "ceil", - common.NativeFunction.TRUNC: "trunc", + common.NativeFunction.CEIL: "dace.math.ceil", + common.NativeFunction.TRUNC: "dace.math.trunc", common.NativeFunction.INT32: "dace.int32", common.NativeFunction.INT64: "dace.int64", common.NativeFunction.FLOAT32: "dace.float32", common.NativeFunction.FLOAT64: "dace.float64", - common.NativeFunction.ERF: "erf", - common.NativeFunction.ERFC: "erfc", + common.NativeFunction.ERF: "dace.math.erf", + common.NativeFunction.ERFC: "dace.math.erfc", common.NativeFunction.ROUND: "nearbyint", common.NativeFunction.ROUND_AWAY_FROM_ZERO: "round", } diff --git a/uv.lock b/uv.lock index 59e8b3010b..b07033c4cc 100644 --- a/uv.lock +++ b/uv.lock @@ -1210,7 +1210,7 @@ wheels = [ [[package]] name = "dace" version = "1.0.0" -source = { git = "https://github.com/GridTools/dace?branch=romanc%2Fstree-v2#d5fbadb626389e425fac5ed93d2a880811eca41f" } +source = { git = "https://github.com/GridTools/dace?branch=romanc%2Fmath-functions#5475d547b76cb44eb876125eb35d6fac08831fdc" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", @@ -1789,7 +1789,7 @@ build = [ { name = "wheel" }, ] dace-cartesian = [ - { name = "dace", version = "1.0.0", source = { git = "https://github.com/GridTools/dace?branch=romanc%2Fstree-v2#d5fbadb626389e425fac5ed93d2a880811eca41f" } }, + { name = "dace", version = "1.0.0", source = { git = "https://github.com/GridTools/dace?branch=romanc%2Fmath-functions#5475d547b76cb44eb876125eb35d6fac08831fdc" } }, ] dace-next = [ { name = "dace", version = "43!2026.4.27", source = { registry = "https://gridtools.github.io/pypi/" } }, @@ -1961,7 +1961,7 @@ build = [ { name = "setuptools", specifier = ">=77.0.3" }, { name = "wheel", specifier = ">=0.33.6" }, ] -dace-cartesian = [{ name = "dace", git = "https://github.com/GridTools/dace?branch=romanc%2Fstree-v2" }] +dace-cartesian = [{ name = "dace", git = "https://github.com/GridTools/dace?branch=romanc%2Fmath-functions" }] dace-next = [{ name = "dace", specifier = "==43!2026.4.27", index = "https://gridtools.github.io/pypi/", conflict = { package = "gt4py", group = "dace-next" } }] dev = [ { name = "atlas4py", specifier = ">=0.41", index = "https://test.pypi.org/simple" }, From 1eec3df54fbd8747867d8fa4b6bfd00d8898b69b Mon Sep 17 00:00:00 2001 From: Roman Cattaneo Date: Mon, 11 May 2026 16:19:35 +0200 Subject: [PATCH 3/7] update dace (fix fmod arguments) --- uv.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uv.lock b/uv.lock index b07033c4cc..437365b901 100644 --- a/uv.lock +++ b/uv.lock @@ -1210,7 +1210,7 @@ wheels = [ [[package]] name = "dace" version = "1.0.0" -source = { git = "https://github.com/GridTools/dace?branch=romanc%2Fmath-functions#5475d547b76cb44eb876125eb35d6fac08831fdc" } +source = { git = "https://github.com/GridTools/dace?branch=romanc%2Fmath-functions#3df061c8aeabcaeea966f79e39a4dbded2628df9" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", "python_full_version >= '3.14' and sys_platform == 'emscripten'", @@ -1789,7 +1789,7 @@ build = [ { name = "wheel" }, ] dace-cartesian = [ - { name = "dace", version = "1.0.0", source = { git = "https://github.com/GridTools/dace?branch=romanc%2Fmath-functions#5475d547b76cb44eb876125eb35d6fac08831fdc" } }, + { name = "dace", version = "1.0.0", source = { git = "https://github.com/GridTools/dace?branch=romanc%2Fmath-functions#3df061c8aeabcaeea966f79e39a4dbded2628df9" } }, ] dace-next = [ { name = "dace", version = "43!2026.4.27", source = { registry = "https://gridtools.github.io/pypi/" } }, From c186e61d14384e25da78d7f26de19b782b30c181 Mon Sep 17 00:00:00 2001 From: Florian Deconinck Date: Fri, 22 May 2026 14:34:57 -0400 Subject: [PATCH 4/7] Add dace:gpu_IJK backend --- src/gt4py/cartesian/backend/dace_backend.py | 19 ++++++++++++++++++- .../storage/cartesian/layout_registry.py | 9 +++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/gt4py/cartesian/backend/dace_backend.py b/src/gt4py/cartesian/backend/dace_backend.py index b7a9a0cece..5bcb8e9e08 100644 --- a/src/gt4py/cartesian/backend/dace_backend.py +++ b/src/gt4py/cartesian/backend/dace_backend.py @@ -920,7 +920,7 @@ def generate_extension(self) -> None: @register class DaceGPUBackend(BaseDaceBackend): - """DaCe python backend using gt4py.cartesian.gtc.""" + """GPU DaCe python with an optimal KJI loop layout""" name = "dace:gpu" languages: ClassVar[dict] = {"computation": "cuda", "bindings": ["python"]} @@ -933,3 +933,20 @@ class DaceGPUBackend(BaseDaceBackend): def generate_extension(self) -> None: return self.make_extension(uses_cuda=True) + + +@register +class DaceGPUBackendIJK(BaseDaceBackend): + """GPU DaCe python with an optimal IJK loop layout""" + + name = "dace:gpu_IJK" + languages: ClassVar[dict] = {"computation": "cuda", "bindings": ["python"]} + storage_info: ClassVar[layout.LayoutInfo] = layout_registry.from_name(name) + MODULE_GENERATOR_CLASS = DaCeCUDAPyExtModuleGenerator + options: ClassVar[GTBackendOptions] = { + **BaseGTBackend.GT_BACKEND_OPTS, + "device_sync": {"versioning": True, "type": bool}, + } + + def generate_extension(self) -> None: + return self.make_extension(uses_cuda=True) diff --git a/src/gt4py/storage/cartesian/layout_registry.py b/src/gt4py/storage/cartesian/layout_registry.py index 4fadc0f7d0..f80c7e3f8d 100644 --- a/src/gt4py/storage/cartesian/layout_registry.py +++ b/src/gt4py/storage/cartesian/layout_registry.py @@ -66,6 +66,15 @@ def register(name: str, info: LayoutInfo) -> None: is_optimal_layout=layout_checker_factory(layout_maker_factory((2, 1, 0))), ), ) +register( + "dace:gpu_IJK", + LayoutInfo( + alignment=32, + device="gpu", + layout_map=layout_maker_factory((0, 1, 2)), + is_optimal_layout=layout_checker_factory(layout_maker_factory((0, 1, 2))), + ), +) register( "debug", LayoutInfo( From 3da968c6eb262b5c3898a42495694d6b9bafced7 Mon Sep 17 00:00:00 2001 From: Florian Deconinck Date: Fri, 22 May 2026 14:35:19 -0400 Subject: [PATCH 5/7] Fix GPU compiler flags when not `-O0` --- src/gt4py/cartesian/utils/compiler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gt4py/cartesian/utils/compiler.py b/src/gt4py/cartesian/utils/compiler.py index 409a4c7e09..ec8dc20de0 100644 --- a/src/gt4py/cartesian/utils/compiler.py +++ b/src/gt4py/cartesian/utils/compiler.py @@ -137,7 +137,7 @@ class GPUCompilerName(enum.Enum): class GPUConfiguration: name: GPUCompilerName """Name identifier of the compiler""" - gpu_compile_flags: list[str] + gpu_compile_flags: str """Compile flags for device code""" binary_path: str """Path to binaries for GPU compiler & tools""" @@ -181,7 +181,7 @@ def gpu_configuration(optimization_level: str) -> GPUConfiguration: return GPUConfiguration( name=name, - gpu_compile_flags=gpu_compile_flags, + gpu_compile_flags=" ".join(gpu_compile_flags).strip(), binary_path=os.path.join(cuda_root, "bin"), include_path=os.path.join(cuda_root, "include"), library_path=library_path, From 08bb317c302c91da03cf1e6e21e6fd39dee1588e Mon Sep 17 00:00:00 2001 From: Roman Cattaneo Date: Thu, 28 May 2026 17:17:08 +0200 Subject: [PATCH 6/7] fixes for running GFDL_1M with orch:dace:cpu:KJI --- src/gt4py/cartesian/backend/dace_backend.py | 21 +++++++++++++------ src/gt4py/cartesian/gtc/dace/oir_to_treeir.py | 4 +--- .../multi_feature_tests/test_suites.py | 5 +---- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/gt4py/cartesian/backend/dace_backend.py b/src/gt4py/cartesian/backend/dace_backend.py index 5bcb8e9e08..d42c44016d 100644 --- a/src/gt4py/cartesian/backend/dace_backend.py +++ b/src/gt4py/cartesian/backend/dace_backend.py @@ -95,6 +95,7 @@ def _sdfg_add_arrays_and_edges( inputs: set[str] | dict[str, dtypes.typeclass], outputs: set[str] | dict[str, dtypes.typeclass], origins: dict[str, tuple[int, ...]], + domain: tuple[int, ...], ) -> None: for name, array in inner_sdfg.arrays.items(): if array.transient: @@ -129,12 +130,20 @@ def _sdfg_add_arrays_and_edges( if axis not in axes: continue o = origin[index] - e = field_info[name].boundary.lower_indices[cartesian_index] + lower, upper = field_info[name].boundary[cartesian_index] s = inner_sdfg.arrays[name].shape[index] - ranges.append( - # s - 1 because ranges are inclusive - (o - max(0, e), o - max(0, e) + s - 1, 1) - ) + if axis == CartesianSpace.Axis.K.name: + d = domain[cartesian_index] + ranges.append( + # max(0, lower) because ... + # d - 1 because ranges are inclusive + (o - max(0, lower), o + upper + d - 1, 1) + ) + else: + ranges.append( + # s - 1 because ranges are inclusive + (o - max(0, lower), o - max(0, lower) + s - 1, 1) + ) index += 1 # Add data dimensions to the range @@ -264,7 +273,7 @@ def freeze_origin_domain_sdfg( nsdfg = state.add_nested_sdfg(inner_sdfg, inputs, outputs) _sdfg_add_arrays_and_edges( - field_info, wrapper_sdfg, state, inner_sdfg, nsdfg, inputs, outputs, origin + field_info, wrapper_sdfg, state, inner_sdfg, nsdfg, inputs, outputs, origin, domain ) # in special case of empty domain, remove entire SDFG. diff --git a/src/gt4py/cartesian/gtc/dace/oir_to_treeir.py b/src/gt4py/cartesian/gtc/dace/oir_to_treeir.py index b75a5119f2..c578fea24e 100644 --- a/src/gt4py/cartesian/gtc/dace/oir_to_treeir.py +++ b/src/gt4py/cartesian/gtc/dace/oir_to_treeir.py @@ -350,7 +350,6 @@ def visit_Stencil(self, node: oir.Stencil) -> tir.TreeRoot: param, field_without_mask_extents[param.name], k_bound, - symbols, ), strides=get_dace_strides(param, symbols), storage=DEFAULT_STORAGE_TYPE[self._device_type], @@ -374,7 +373,7 @@ def visit_Stencil(self, node: oir.Stencil) -> tir.TreeRoot: # than persistent will yield issues with memory leaks. containers[field.name] = data.Array( dtype=utils.data_type_to_dace_typeclass(field.dtype), - shape=get_dace_shape(field, field_extent, k_bound, symbols), + shape=get_dace_shape(field, field_extent, k_bound), strides=get_dace_strides(field, symbols), transient=True, lifetime=dtypes.AllocationLifetime.Persistent, @@ -532,7 +531,6 @@ def get_dace_shape( field: oir.FieldDecl, extent: definitions.Extent, k_bound: tuple[int, int], - symbols: tir.SymbolDict, ) -> list[symbolic.symbol]: shape = [] for index, axis in enumerate(tir.Axis.dims_3d()): diff --git a/tests/cartesian_tests/integration_tests/multi_feature_tests/test_suites.py b/tests/cartesian_tests/integration_tests/multi_feature_tests/test_suites.py index 91419f1932..89c988a526 100644 --- a/tests/cartesian_tests/integration_tests/multi_feature_tests/test_suites.py +++ b/tests/cartesian_tests/integration_tests/multi_feature_tests/test_suites.py @@ -800,10 +800,7 @@ class TestVariableKAndReadOutside(gt_testing.StencilTestSuite): def definition(field_in, field_out, index): with computation(PARALLEL), interval(1, None): - field_out[0, 0, 0] = ( - field_in[0, 0, index] # noqa: F841 [unused-variable] - + field_in[0, 0, -2] - ) + field_out[0, 0, 0] = field_in[0, 0, index] + field_in[0, 0, -2] def validation(field_in, field_out, index, *, domain, origin): idx = 1 + (np.arange(domain[-1]) + index)[1:] From 08100b8505a6ce655a8b71043da514f3a6b8634a Mon Sep 17 00:00:00 2001 From: Roman Cattaneo Date: Thu, 28 May 2026 17:28:41 +0200 Subject: [PATCH 7/7] fix pyproject.toml & uv.lock files after merge with main --- pyproject.toml | 4 ---- uv.lock | 29 ++++------------------------- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3560ec3d80..a10488c7a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -476,10 +476,6 @@ url = 'https://gridtools.github.io/pypi/' # dace = {index = "gridtools"} [tool.uv.sources] atlas4py = {index = "test.pypi"} -dace = [ - {git = "https://github.com/GridTools/dace", branch = "romanc/math-functions", group = "dace-cartesian"}, - {index = "gridtools", group = "dace-next"} -] # -- versioningit -- [tool.versioningit] diff --git a/uv.lock b/uv.lock index 7e06c6bb11..7027f7d4f5 100644 --- a/uv.lock +++ b/uv.lock @@ -1206,23 +1206,8 @@ wheels = [ [[package]] name = "dace" -version = "1.0.0" -source = { git = "https://github.com/GridTools/dace?branch=romanc%2Fmath-functions#3df061c8aeabcaeea966f79e39a4dbded2628df9" } -resolution-markers = [ - "python_full_version >= '3.14' and sys_platform == 'win32'", - "python_full_version >= '3.14' and sys_platform == 'emscripten'", - "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", - "python_full_version == '3.13.*' and sys_platform == 'win32'", - "python_full_version == '3.13.*' and sys_platform == 'emscripten'", - "python_full_version == '3.13.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", - "python_full_version == '3.12.*' and sys_platform == 'win32'", - "python_full_version == '3.12.*' and sys_platform == 'emscripten'", - "python_full_version == '3.12.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", - "python_full_version == '3.11.*' and sys_platform == 'win32'", - "python_full_version == '3.11.*' and sys_platform == 'emscripten'", - "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", - "python_full_version < '3.11'", -] +version = "2.0.0a3" +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astunparse" }, { name = "dill" }, @@ -1749,12 +1734,6 @@ build = [ { name = "setuptools" }, { name = "wheel" }, ] -dace-cartesian = [ - { name = "dace", version = "1.0.0", source = { git = "https://github.com/GridTools/dace?branch=romanc%2Fmath-functions#3df061c8aeabcaeea966f79e39a4dbded2628df9" } }, -] -dace-next = [ - { name = "dace", version = "43!2026.4.27", source = { registry = "https://gridtools.github.io/pypi/" } }, -] dev = [ { name = "atlas4py" }, { name = "coverage", extra = ["toml"] }, @@ -1923,9 +1902,9 @@ build = [ { name = "setuptools", specifier = ">=77.0.3" }, { name = "wheel", specifier = ">=0.33.6" }, ] -dace-cartesian = [{ name = "dace", git = "https://github.com/GridTools/dace?branch=romanc%2Fmath-functions" }] -dace-next = [{ name = "dace", specifier = "==43!2026.4.27", index = "https://gridtools.github.io/pypi/", conflict = { package = "gt4py", group = "dace-next" } }] dev = [ + { name = "atlas4py", specifier = ">=0.41", index = "https://test.pypi.org/simple" }, + { name = "coverage", extras = ["toml"], specifier = ">=7.6.1" }, { name = "cython", specifier = ">=3.0.0" }, { name = "esbonio", specifier = ">=0.16.0" }, { name = "hypothesis", specifier = ">=6.0.0" },