diff --git a/include/oneapi/tbb.h b/include/oneapi/tbb.h index ad96011373..c52eb9e228 100644 --- a/include/oneapi/tbb.h +++ b/include/oneapi/tbb.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2005-2023 Intel Corporation + Copyright (c) 2005-2024 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -28,9 +28,7 @@ #include "oneapi/tbb/blocked_range.h" #include "oneapi/tbb/blocked_range2d.h" #include "oneapi/tbb/blocked_range3d.h" -#if TBB_PREVIEW_BLOCKED_RANGE_ND -#include "tbb/blocked_rangeNd.h" -#endif +#include "oneapi/tbb/blocked_nd_range.h" #include "oneapi/tbb/cache_aligned_allocator.h" #include "oneapi/tbb/combinable.h" #include "oneapi/tbb/concurrent_hash_map.h" diff --git a/include/oneapi/tbb/blocked_rangeNd.h b/include/oneapi/tbb/blocked_nd_range.h similarity index 58% rename from include/oneapi/tbb/blocked_rangeNd.h rename to include/oneapi/tbb/blocked_nd_range.h index a7ba137506..3a9697896f 100644 --- a/include/oneapi/tbb/blocked_rangeNd.h +++ b/include/oneapi/tbb/blocked_nd_range.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2017-2021 Intel Corporation + Copyright (c) 2017-2024 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,12 +14,8 @@ limitations under the License. */ -#ifndef __TBB_blocked_rangeNd_H -#define __TBB_blocked_rangeNd_H - -#if !TBB_PREVIEW_BLOCKED_RANGE_ND - #error Set TBB_PREVIEW_BLOCKED_RANGE_ND to include blocked_rangeNd.h -#endif +#ifndef __TBB_blocked_nd_range_H +#define __TBB_blocked_nd_range_H #include // std::any_of #include @@ -28,6 +24,7 @@ #include "detail/_config.h" #include "detail/_template_helpers.h" // index_sequence, make_index_sequence +#include "detail/_namespace_injection.h" #include "detail/_range_common.h" #include "blocked_range.h" @@ -37,45 +34,56 @@ namespace detail { namespace d1 { /* - The blocked_rangeNd_impl uses make_index_sequence to automatically generate a ctor with + The blocked_nd_range_impl uses make_index_sequence to automatically generate a ctor with exactly N arguments of the type tbb::blocked_range. Such ctor provides an opportunity to use braced-init-list parameters to initialize each dimension. Use of parameters, whose representation is a braced-init-list, but they're not std::initializer_list or a reference to one, produces a non-deduced context within template argument deduction. - NOTE: blocked_rangeNd must be exactly a templated alias to the blocked_rangeNd_impl + NOTE: blocked_nd_range must be exactly a templated alias to the blocked_nd_range_impl (and not e.g. a derived class), otherwise it would need to declare its own ctor facing the same problem that the impl class solves. */ template> __TBB_requires(blocked_range_value) -class blocked_rangeNd_impl; +class blocked_nd_range_impl; template __TBB_requires(blocked_range_value) -class blocked_rangeNd_impl> { +class blocked_nd_range_impl> { public: //! Type of a value. using value_type = Value; -private: - //! Helper type to construct range with N tbb::blocked_range objects. - template - using dim_type_helper = tbb::blocked_range; + //! Type of a dimension range. + using dim_range_type = tbb::blocked_range; -public: - blocked_rangeNd_impl() = delete; + //! Type for the size of a range. + using size_type = typename dim_range_type::size_type; + + blocked_nd_range_impl() = delete; //! Constructs N-dimensional range over N half-open intervals each represented as tbb::blocked_range. - blocked_rangeNd_impl(const dim_type_helper&... args) : my_dims{ {args...} } {} + blocked_nd_range_impl(const indexed_t&... args) : my_dims{ {args...} } {} + +#if __clang__ && __TBB_CLANG_VERSION < 140000 + // On clang prior to version 14.0.0, passing a single braced init list to the constructor of blocked_nd_range + // matches better on the C array constructor and generates compile-time error because of unexpected size + // Adding constraints for this constructor to force the compiler to drop it from overload resolution if the size is unexpected + template ::type> + blocked_nd_range_impl(const value_type (&size)[M], size_type grainsize = 1) : +#else + blocked_nd_range_impl(const value_type (&size)[N], size_type grainsize = 1) : +#endif + my_dims { dim_range_type(0, size[Is], grainsize)... } {} //! Dimensionality of a range. - static constexpr unsigned int ndims() { return N; } + static constexpr unsigned int dim_count() { return N; } //! Range in certain dimension. - const tbb::blocked_range& dim(unsigned int dimension) const { + const dim_range_type& dim(unsigned int dimension) const { __TBB_ASSERT(dimension < N, "out of bound"); return my_dims[dimension]; } @@ -86,44 +94,45 @@ class blocked_rangeNd_impl> { //! True if at least one dimension is empty. bool empty() const { - return std::any_of(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range& d) { + return std::any_of(my_dims.begin(), my_dims.end(), [](const dim_range_type& d) { return d.empty(); }); } //! True if at least one dimension is divisible. bool is_divisible() const { - return std::any_of(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range& d) { + return std::any_of(my_dims.begin(), my_dims.end(), [](const dim_range_type& d) { return d.is_divisible(); }); } - blocked_rangeNd_impl(blocked_rangeNd_impl& r, proportional_split proportion) : my_dims(r.my_dims) { + blocked_nd_range_impl(blocked_nd_range_impl& r, proportional_split proportion) : my_dims(r.my_dims) { do_split(r, proportion); } - blocked_rangeNd_impl(blocked_rangeNd_impl& r, split proportion) : my_dims(r.my_dims) { + blocked_nd_range_impl(blocked_nd_range_impl& r, split proportion) : my_dims(r.my_dims) { do_split(r, proportion); } private: - static_assert(N != 0, "zero dimensional blocked_rangeNd can't be constructed"); + static_assert(N != 0, "zero dimensional blocked_nd_range can't be constructed"); //! Ranges in each dimension. - std::array, N> my_dims; + std::array my_dims; template - void do_split(blocked_rangeNd_impl& r, split_type proportion) { - static_assert((std::is_same::value || std::is_same::value), "type of split object is incorrect"); + void do_split(blocked_nd_range_impl& r, split_type proportion) { + static_assert((std::is_same::value || std::is_same::value), + "type of split object is incorrect"); __TBB_ASSERT(r.is_divisible(), "can't split not divisible range"); - auto my_it = std::max_element(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range& first, const tbb::blocked_range& second) { - return (first.size() * second.grainsize() < second.size() * first.grainsize()); + auto my_it = std::max_element(my_dims.begin(), my_dims.end(), [](const dim_range_type& first, const dim_range_type& second) { + return (first.size() * double(second.grainsize()) < second.size() * double(first.grainsize())); }); auto r_it = r.my_dims.begin() + (my_it - my_dims.begin()); - my_it->my_begin = tbb::blocked_range::do_split(*r_it, proportion); + my_it->my_begin = dim_range_type::do_split(*r_it, proportion); // (!(my_it->my_begin < r_it->my_end) && !(r_it->my_end < my_it->my_begin)) equals to // (my_it->my_begin == r_it->my_end), but we can't use operator== due to Value concept @@ -133,15 +142,14 @@ class blocked_rangeNd_impl> { }; template -using blocked_rangeNd = blocked_rangeNd_impl; +using blocked_nd_range = blocked_nd_range_impl; } // namespace d1 } // namespace detail inline namespace v1 { -using detail::d1::blocked_rangeNd; +using detail::d1::blocked_nd_range; } // namespace v1 } // namespace tbb -#endif /* __TBB_blocked_rangeNd_H */ - +#endif /* __TBB_blocked_nd_range_H */ diff --git a/include/oneapi/tbb/blocked_range.h b/include/oneapi/tbb/blocked_range.h index 12862fa2a1..5193faffd5 100644 --- a/include/oneapi/tbb/blocked_range.h +++ b/include/oneapi/tbb/blocked_range.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2005-2021 Intel Corporation + Copyright (c) 2005-2024 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -152,7 +152,7 @@ class blocked_range { template __TBB_requires(blocked_range_value) - friend class blocked_rangeNd_impl; + friend class blocked_nd_range_impl; }; } // namespace d1 diff --git a/include/oneapi/tbb/detail/_template_helpers.h b/include/oneapi/tbb/detail/_template_helpers.h index 50ce3d2d3b..a20c5af5c3 100644 --- a/include/oneapi/tbb/detail/_template_helpers.h +++ b/include/oneapi/tbb/detail/_template_helpers.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2005-2023 Intel Corporation + Copyright (c) 2005-2024 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -106,6 +106,10 @@ using make_index_sequence = typename make_index_sequence_impl::type; #endif /* __TBB_CPP14_INTEGER_SEQUENCE_PRESENT */ +//! Attach an index to a type to use it with an index sequence +template +using indexed_t = T; + #if __TBB_CPP17_LOGICAL_OPERATIONS_PRESENT using std::conjunction; using std::disjunction; diff --git a/include/tbb/blocked_rangeNd.h b/include/tbb/blocked_nd_range.h similarity index 86% rename from include/tbb/blocked_rangeNd.h rename to include/tbb/blocked_nd_range.h index 0c0fb7303a..70ca73af4b 100644 --- a/include/tbb/blocked_rangeNd.h +++ b/include/tbb/blocked_nd_range.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2017-2021 Intel Corporation + Copyright (c) 2017-2024 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,4 +14,4 @@ limitations under the License. */ -#include "../oneapi/tbb/blocked_rangeNd.h" +#include "../oneapi/tbb/blocked_nd_range.h" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fb4a78bdbb..0ab4d7e8c8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -537,7 +537,7 @@ if (TARGET TBB::tbb) tbb_add_test(SUBDIR conformance NAME conformance_blocked_range DEPENDENCIES TBB::tbb) tbb_add_test(SUBDIR conformance NAME conformance_blocked_range2d DEPENDENCIES TBB::tbb) tbb_add_test(SUBDIR conformance NAME conformance_blocked_range3d DEPENDENCIES TBB::tbb) - tbb_add_test(SUBDIR conformance NAME conformance_blocked_rangeNd DEPENDENCIES TBB::tbb) + tbb_add_test(SUBDIR conformance NAME conformance_blocked_nd_range DEPENDENCIES TBB::tbb) tbb_add_test(SUBDIR conformance NAME conformance_concurrent_vector DEPENDENCIES TBB::tbb) if (NOT TBB_TCM_TESTING) tbb_add_test(SUBDIR conformance NAME conformance_global_control DEPENDENCIES TBB::tbb) diff --git a/test/common/config.h b/test/common/config.h index aa75790c3f..c7ff8ba63a 100644 --- a/test/common/config.h +++ b/test/common/config.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2005-2021 Intel Corporation + Copyright (c) 2005-2024 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -36,9 +36,6 @@ #ifndef TBB_PREVIEW_VARIADIC_PARALLEL_INVOKE #define TBB_PREVIEW_VARIADIC_PARALLEL_INVOKE 1 #endif -#ifndef TBB_PREVIEW_BLOCKED_RANGE_ND -#define TBB_PREVIEW_BLOCKED_RANGE_ND 1 -#endif #ifndef TBB_PREVIEW_ISOLATED_TASK_GROUP #define TBB_PREVIEW_ISOLATED_TASK_GROUP 1 #endif diff --git a/test/conformance/conformance_blocked_rangeNd.cpp b/test/conformance/conformance_blocked_nd_range.cpp similarity index 79% rename from test/conformance/conformance_blocked_rangeNd.cpp rename to test/conformance/conformance_blocked_nd_range.cpp index 52faac52ca..999eacb3c6 100644 --- a/test/conformance/conformance_blocked_rangeNd.cpp +++ b/test/conformance/conformance_blocked_nd_range.cpp @@ -19,11 +19,10 @@ #include "common/utils_assert.h" #include "common/utils_concurrency_limit.h" -//! \file conformance_blocked_rangeNd.cpp -//! \brief Test for [preview] functionality +//! \file conformance_blocked_nd_range.cpp +//! \brief Test for [algorithms.blocked_nd_range] specification -#define TBB_PREVIEW_BLOCKED_RANGE_ND 1 -#include "oneapi/tbb/blocked_rangeNd.h" +#include "oneapi/tbb/blocked_nd_range.h" #include "oneapi/tbb/parallel_for.h" #include "oneapi/tbb/global_control.h" @@ -160,10 +159,10 @@ int MakeInt(int i) { return i; } template void SerialTest() { - static_assert((oneapi::tbb::blocked_rangeNd::ndims() == oneapi::tbb::blocked_rangeNd::ndims()), + static_assert((oneapi::tbb::blocked_nd_range::dim_count() == oneapi::tbb::blocked_nd_range::dim_count()), "different amount of dimensions"); - using range_t = oneapi::tbb::blocked_rangeNd; + using range_t = oneapi::tbb::blocked_nd_range; using utils_t = range_utils; // Generate empty range @@ -171,7 +170,7 @@ void SerialTest() { utils::AssertSameType(r.is_divisible(), bool()); utils::AssertSameType(r.empty(), bool()); - utils::AssertSameType(range_t::ndims(), 0U); + utils::AssertSameType(range_t::dim_count(), 0U); REQUIRE((r.empty() == utils_t::is_empty(r) && r.empty())); REQUIRE(r.is_divisible() == utils_t::is_divisible(r)); @@ -190,7 +189,7 @@ template<> void SerialTest<0>() {} template void ParallelTest() { - using range_t = oneapi::tbb::blocked_rangeNd; + using range_t = oneapi::tbb::blocked_nd_range; using utils_t = range_utils; // Max size is 1 << 20 - 1 bytes @@ -210,28 +209,45 @@ void ParallelTest() { } template<> void ParallelTest<0>() {} -//! Testing blocked_rangeNd construction +//! Testing blocked_nd_range construction //! \brief \ref interface TEST_CASE("Construction") { - oneapi::tbb::blocked_rangeNd{ { 0,13,3 } }; + oneapi::tbb::blocked_nd_range{ { 0,13,3 } }; - oneapi::tbb::blocked_rangeNd{ oneapi::tbb::blocked_range{ 0,13,3 } }; + oneapi::tbb::blocked_nd_range{ oneapi::tbb::blocked_range{ 0,13,3 } }; - oneapi::tbb::blocked_rangeNd(oneapi::tbb::blocked_range(-8923, 8884, 13), oneapi::tbb::blocked_range(-8923, 5, 13)); + oneapi::tbb::blocked_nd_range(oneapi::tbb::blocked_range(-8923, 8884, 13), oneapi::tbb::blocked_range(-8923, 5, 13)); - oneapi::tbb::blocked_rangeNd({ -8923, 8884, 13 }, { -8923, 8884, 13 }); + oneapi::tbb::blocked_nd_range({ -8923, 8884, 13 }, { -8923, 8884, 13 }); oneapi::tbb::blocked_range r1(0, 13); oneapi::tbb::blocked_range r2(-12, 23); - oneapi::tbb::blocked_rangeNd({ { -8923, 8884, 13 }, r1}); + oneapi::tbb::blocked_nd_range({ { -8923, 8884, 13 }, r1}); - oneapi::tbb::blocked_rangeNd({ r2, r1 }); + oneapi::tbb::blocked_nd_range({ r2, r1 }); - oneapi::tbb::blocked_rangeNd(r1, r2); + oneapi::tbb::blocked_nd_range(r1, r2); - oneapi::tbb::blocked_rangeNd({ MakeAbstractValue(-3), MakeAbstractValue(13), 8 }, + int sizes[] = {174, 39, 2481, 93}; + oneapi::tbb::blocked_nd_range rNd_1(sizes, /*grainsize*/7); + + oneapi::tbb::blocked_nd_range rNd_2({174, 39, 2481, 93}, /*grainsize*/11); + + for (unsigned i = 0; i < rNd_1.dim_count(); ++i) { + oneapi::tbb::blocked_nd_range::dim_range_type dim1 = rNd_1.dim(i); + oneapi::tbb::blocked_nd_range::dim_range_type dim2 = rNd_2.dim(i); + REQUIRE(dim1.begin()==0); + REQUIRE(dim2.begin()==0); + unsigned int szi = sizes[i]; // to compare with unsigned integrals without warnings + REQUIRE(dim1.size()==szi); + REQUIRE(dim2.size()==szi); + REQUIRE(dim1.grainsize()==7); + REQUIRE(dim2.grainsize()==11); + } + + oneapi::tbb::blocked_nd_range({ MakeAbstractValue(-3), MakeAbstractValue(13), 8 }, { MakeAbstractValue(-53), MakeAbstractValue(23), 2 }, { MakeAbstractValue(-23), MakeAbstractValue(33), 1 }, { MakeAbstractValue(-13), MakeAbstractValue(43), 7 }); @@ -239,14 +255,14 @@ TEST_CASE("Construction") { static const std::size_t N = 4; -//! Testing blocked_rangeNd interface +//! Testing blocked_nd_range interface //! \brief \ref interface \ref requirement TEST_CASE("Serial test") { SerialTest(); } #if !EMSCRIPTEN -//! Testing blocked_rangeNd interface with parallel_for +//! Testing blocked_nd_range interface with parallel_for //! \brief \ref requirement TEST_CASE("Parallel test") { for ( auto concurrency_level : utils::concurrency_range() ) { @@ -256,13 +272,13 @@ TEST_CASE("Parallel test") { } #endif -//! Testing blocked_rangeNd with proportional splitting +//! Testing blocked_nd_range with proportional splitting //! \brief \ref interface \ref requirement -TEST_CASE("blocked_rangeNd proportional splitting") { - oneapi::tbb::blocked_rangeNd original{{0, 100}, {0, 100}}; - oneapi::tbb::blocked_rangeNd first(original); +TEST_CASE("blocked_nd_range proportional splitting") { + oneapi::tbb::blocked_nd_range original{{0, 100}, {0, 100}}; + oneapi::tbb::blocked_nd_range first(original); oneapi::tbb::proportional_split ps(3, 1); - oneapi::tbb::blocked_rangeNd second(first, ps); + oneapi::tbb::blocked_nd_range second(first, ps); int expected_first_end = static_cast( original.dim(0).begin() + ps.left() * (original.dim(0).end() - original.dim(0).begin()) / (ps.left() + ps.right()) diff --git a/test/tbb/test_blocked_range.cpp b/test/tbb/test_blocked_range.cpp index 651122220a..2443d590e1 100644 --- a/test/tbb/test_blocked_range.cpp +++ b/test/tbb/test_blocked_range.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2005-2021 Intel Corporation + Copyright (c) 2005-2024 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -24,11 +24,10 @@ #include "tbb/blocked_range.h" #include "tbb/blocked_range2d.h" #include "tbb/blocked_range3d.h" -#define TBB_PREVIEW_BLOCKED_RANGE_ND 1 -#include "tbb/blocked_rangeNd.h" +#include "tbb/blocked_nd_range.h" //! \file test_blocked_range.cpp -//! \brief Test for [algorithms.blocked_range] specification +//! \brief Test for [algorithms.blocked_range algorithms.blocked_range2d algorithms.blocked_range3d algorithms.blocked_nd_range] specification #include //for std::pair #include @@ -120,12 +119,12 @@ template void test_blocked_range3d_col_invalid_constraint() {} template -concept well_formed_blocked_range_Nd_instantiation_basic = requires { - typename tbb::blocked_rangeNd; +concept well_formed_blocked_nd_range_instantiation_basic = requires { + typename tbb::blocked_nd_range; }; template -concept well_formed_blocked_range_Nd_instantiation = ( ... && well_formed_blocked_range_Nd_instantiation_basic ); +concept well_formed_blocked_nd_range_instantiation = ( ... && well_formed_blocked_nd_range_instantiation_basic ); //! \brief \ref error_guessing TEST_CASE("constraints for blocked_range value") { @@ -180,13 +179,13 @@ TEST_CASE("constraints for blocked_range3d value") { } //! \brief \ref error_guessing -TEST_CASE("constraints for blocked_rangeNd value") { +TEST_CASE("constraints for blocked_nd_range value") { using namespace test_concepts::blocked_range_value; using const_iterator = typename std::vector::const_iterator; - static_assert(well_formed_blocked_range_Nd_instantiation); + static_assert(well_formed_blocked_nd_range_instantiation); - static_assert(!well_formed_blocked_range_Nd_instantiation); diff --git a/test/tbb/test_hw_concurrency.cpp b/test/tbb/test_hw_concurrency.cpp index 16d4067b83..115a8f34be 100644 --- a/test/tbb/test_hw_concurrency.cpp +++ b/test/tbb/test_hw_concurrency.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2005-2021 Intel Corporation + Copyright (c) 2005-2024 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -47,8 +47,7 @@ #include "tbb/blocked_range.h" #include "tbb/blocked_range2d.h" #include "tbb/blocked_range3d.h" -#define TBB_PREVIEW_BLOCKED_RANGE_ND 1 -#include "tbb/blocked_rangeNd.h" +#include "tbb/blocked_nd_range.h" // Declaration of global objects are needed to check that // it does not initialize the task scheduler, and in particular @@ -87,7 +86,7 @@ tbb::tick_count test_tc; tbb::blocked_range br(0, 1); tbb::blocked_range2d br2d(0, 1, 0, 1); tbb::blocked_range3d br3d(0, 1, 0, 1, 0, 1); -tbb::blocked_rangeNd brNd({0, 1}, {0, 1}); +tbb::blocked_nd_range brNd({0, 1}, {0, 1}); //! \brief \ref error_guessing TEST_CASE("Check absence of scheduler initialization") { diff --git a/test/tbb/test_tbb_header.cpp b/test/tbb/test_tbb_header.cpp index a7b0791ef7..122af5ec08 100644 --- a/test/tbb/test_tbb_header.cpp +++ b/test/tbb/test_tbb_header.cpp @@ -172,7 +172,6 @@ static void TestExceptionClassesExports () { // These names are only tested in "preview" configuration // When a feature becomes fully supported, its names should be moved to the main test static void TestPreviewNames() { - TestTypeDefinitionPresence2( blocked_rangeNd ); TestTypeDefinitionPresence2( concurrent_lru_cache ); TestTypeDefinitionPresence( isolated_task_group ); } @@ -238,6 +237,7 @@ static void DefinitionPresence() { TestTypeDefinitionPresence( blocked_range ); TestTypeDefinitionPresence( blocked_range2d ); TestTypeDefinitionPresence( blocked_range3d ); + TestTypeDefinitionPresence2( blocked_nd_range ); TestTypeDefinitionPresence( collaborative_once_flag ); TestFuncDefinitionPresence( collaborative_call_once, (tbb::collaborative_once_flag&, const Body&), void ); TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, const Body&), void );