diff --git a/include/gridtools/fn/backend/gpu.hpp b/include/gridtools/fn/backend/gpu.hpp index 5827fe7a2..ad5115533 100644 --- a/include/gridtools/fn/backend/gpu.hpp +++ b/include/gridtools/fn/backend/gpu.hpp @@ -139,16 +139,27 @@ namespace gridtools::fn::backend { } }; + template + bool is_domain_empty(const Sizes &sizes) { + return tuple_util::host::apply([](auto... sizes) { return ((sizes == 0) || ...); }, sizes); + } + template void apply_stencil_stage(gpu const &g, Sizes const &sizes, StencilStage, MakeIterator make_iterator, Composite &&composite) { + + if (is_domain_empty(sizes)) { + return; + } + auto ptr_holder = sid::get_origin(std::forward(composite)); auto strides = sid::get_strides(std::forward(composite)); auto [blocks, threads] = blocks_and_threads(sizes); + assert(threads.x > 0 && threads.y > 0 && threads.z > 0); cuda_util::launch(blocks, threads, 0, @@ -190,12 +201,18 @@ namespace gridtools::fn::backend { Composite &&composite, Vertical, Seed seed) { + + if (is_domain_empty(sizes)) { + return; + } + auto ptr_holder = sid::get_origin(std::forward(composite)); auto strides = sid::get_strides(std::forward(composite)); auto h_sizes = hymap::canonicalize_and_remove_key(sizes); int v_size = at_key(sizes); auto [blocks, threads] = blocks_and_threads(h_sizes); + assert(threads.x > 0 && threads.y > 0 && threads.z > 0); cuda_util::launch(blocks, threads, 0, diff --git a/tests/regression/fn/CMakeLists.txt b/tests/regression/fn/CMakeLists.txt index 1ea59e8eb..6ea25e97d 100644 --- a/tests/regression/fn/CMakeLists.txt +++ b/tests/regression/fn/CMakeLists.txt @@ -26,4 +26,5 @@ gridtools_add_fn_regression_test(fn_copy SOURCES fn_copy.cpp PERFTEST) gridtools_add_fn_regression_test(fn_unstructured_nabla SOURCES fn_unstructured_nabla.cpp PERFTEST) gridtools_add_fn_regression_test(fn_tridiagonal_solve SOURCES fn_tridiagonal_solve.cpp PERFTEST) gridtools_add_fn_regression_test(fn_cartesian_vertical_advection SOURCES fn_cartesian_vertical_advection.cpp PERFTEST) +gridtools_add_fn_regression_test(fn_empty_domain SOURCES fn_empty_domain.cpp) gridtools_add_fn_regression_test(fn_vertical_indirection SOURCES fn_vertical_indirection.cpp) diff --git a/tests/regression/fn/fn_empty_domain.cpp b/tests/regression/fn/fn_empty_domain.cpp new file mode 100644 index 000000000..f0160d96a --- /dev/null +++ b/tests/regression/fn/fn_empty_domain.cpp @@ -0,0 +1,55 @@ +/* + * GridTools + * + * Copyright (c) 2014-2021, ETH Zurich + * All rights reserved. + * + * Please, refer to the LICENSE file in the root directory. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +namespace { + using namespace gridtools; + using namespace fn; + using namespace literals; + + struct empty_stencil { + GT_FUNCTION constexpr auto operator()() const { + return []() { return 0.0f; }; + } + }; + + GT_REGRESSION_TEST(empty_domain_stencil, test_environment<>, fn_backend_t) { + auto out = TypeParam::make_storage([](...) { return 0; }); + + auto domain = unstructured_domain(tuple{0, 0}, tuple{0, 0}); + auto backend = make_backend(fn_backend_t{}, domain); + backend.stencil_executor()().arg(out).assign(0_c, empty_stencil{}).execute(); + } + + struct empty_column : fwd { + static GT_FUNCTION constexpr auto prologue() { + return tuple(scan_pass([](auto acc) { return acc; }, host_device::identity())); + } + + static GT_FUNCTION constexpr auto body() { + return scan_pass([](auto acc) { return acc; }, host_device::identity()); + } + }; + + GT_REGRESSION_TEST(empty_domain_column, vertical_test_environment<>, fn_backend_t) { + auto out = TypeParam::make_storage([](...) { return 0; }); + + auto domain = unstructured_domain(tuple{0, 0}, tuple{0, 0}); + auto backend = make_backend(fn_backend_t{}, domain); + backend.vertical_executor()().arg(out).assign(0_c, empty_column{}, 0.0f).execute(); + } + +} // namespace