Skip to content
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f71a22a
Fixed
tobiasweinzierl80 Jul 13, 2024
b9ee745
Adopted copyright dates.
tobiasweinzierl80 Jul 16, 2024
f04ed52
Fixed two bugs
tobiasweinzierl80 Jul 16, 2024
426ece9
Added the includes as per MR remark
tobiasweinzierl80 Jul 19, 2024
2c09180
Work in a review remark from Mike
tobiasweinzierl80 Aug 24, 2024
d0803ce
Rename ndims to dim_count
sasalla23 Aug 27, 2024
07dfde9
Implement ctor changes discussed in the spec
sasalla23 Aug 28, 2024
aca13b9
Change back from std::vector to std::array to store dimensions
sasalla23 Aug 28, 2024
d1c3c9d
Remove unnecessary assertions and mentions of vector
sasalla23 Aug 29, 2024
34e9771
Revert changed include of blocked_range.h
sasalla23 Aug 30, 2024
6a1ac40
Revert unnecessary copyright update
akukanov Sep 3, 2024
9570abc
Match the current specification draft. Use public types internally.
akukanov Sep 3, 2024
cdd4f79
Rename the helper type, add a comment
akukanov Sep 3, 2024
8bfd861
Fix CI errors
akukanov Sep 3, 2024
0225463
Convert to double for size-to-grainsize ratio computation, similar to…
akukanov Sep 3, 2024
bf1bc6c
Add a test for the new constructor
akukanov Sep 3, 2024
7013262
Fix the test
akukanov Sep 3, 2024
63b8d74
Fix the test - 2
akukanov Sep 3, 2024
f65270e
Fix the test - 3
akukanov Sep 3, 2024
a9e18b7
Fix the constructor to work with a braced-init-list argument
akukanov Sep 5, 2024
a84ed3e
Fix "comparison of integers of different signs"
akukanov Sep 5, 2024
ac927fc
Satisfy doctest
akukanov Sep 5, 2024
46a9f0a
Rename to blocked_nd_range
akukanov Oct 10, 2024
93f3a38
Update copyright year
akukanov Oct 10, 2024
99fc103
Correct test traceability tags
akukanov Oct 16, 2024
eb5489d
Add a workaround for clang < 14.0
akukanov Nov 5, 2024
85f53a5
Complete removal of the preview status
akukanov Nov 5, 2024
fa0db8e
Update copyright
Nov 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions include/oneapi/tbb.h
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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 <algorithm> // std::any_of
#include <array>
Expand All @@ -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"
Expand All @@ -37,45 +34,56 @@ namespace detail {
namespace d1 {

/*
The blocked_rangeNd_impl uses make_index_sequence<N> to automatically generate a ctor with
The blocked_nd_range_impl uses make_index_sequence<N> to automatically generate a ctor with
exactly N arguments of the type tbb::blocked_range<Value>. 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<typename Value, unsigned int N, typename = detail::make_index_sequence<N>>
__TBB_requires(blocked_range_value<Value>)
class blocked_rangeNd_impl;
class blocked_nd_range_impl;

template<typename Value, unsigned int N, std::size_t... Is>
__TBB_requires(blocked_range_value<Value>)
class blocked_rangeNd_impl<Value, N, detail::index_sequence<Is...>> {
class blocked_nd_range_impl<Value, N, detail::index_sequence<Is...>> {
public:
//! Type of a value.
using value_type = Value;

private:
//! Helper type to construct range with N tbb::blocked_range<value_type> objects.
template<std::size_t>
using dim_type_helper = tbb::blocked_range<value_type>;
//! Type of a dimension range.
using dim_range_type = tbb::blocked_range<value_type>;

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<Value>.
blocked_rangeNd_impl(const dim_type_helper<Is>&... args) : my_dims{ {args...} } {}
blocked_nd_range_impl(const indexed_t<dim_range_type, Is>&... 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<T, 1>
// 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 <unsigned int M, typename = typename std::enable_if<M == N>::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<value_type>& 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];
}
Expand All @@ -86,44 +94,45 @@ class blocked_rangeNd_impl<Value, N, detail::index_sequence<Is...>> {

//! 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<value_type>& 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<value_type>& 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<tbb::blocked_range<value_type>, N> my_dims;
std::array<dim_range_type, N> my_dims;

template<typename split_type>
void do_split(blocked_rangeNd_impl& r, split_type proportion) {
static_assert((std::is_same<split_type, split>::value || std::is_same<split_type, proportional_split>::value), "type of split object is incorrect");
void do_split(blocked_nd_range_impl& r, split_type proportion) {
static_assert((std::is_same<split_type, split>::value || std::is_same<split_type, proportional_split>::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<value_type>& first, const tbb::blocked_range<value_type>& 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<value_type>::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
Expand All @@ -133,15 +142,14 @@ class blocked_rangeNd_impl<Value, N, detail::index_sequence<Is...>> {
};

template<typename Value, unsigned int N>
using blocked_rangeNd = blocked_rangeNd_impl<Value, N>;
using blocked_nd_range = blocked_nd_range_impl<Value, N>;

} // 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 */
4 changes: 2 additions & 2 deletions include/oneapi/tbb/blocked_range.h
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -152,7 +152,7 @@ class blocked_range {

template<typename DimValue, unsigned int N, typename>
__TBB_requires(blocked_range_value<DimValue>)
friend class blocked_rangeNd_impl;
friend class blocked_nd_range_impl;
};

} // namespace d1
Expand Down
6 changes: 5 additions & 1 deletion include/oneapi/tbb/detail/_template_helpers.h
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -106,6 +106,10 @@ using make_index_sequence = typename make_index_sequence_impl<N>::type;

#endif /* __TBB_CPP14_INTEGER_SEQUENCE_PRESENT */

//! Attach an index to a type to use it with an index sequence
template<typename T, std::size_t>
using indexed_t = T;

#if __TBB_CPP17_LOGICAL_OPERATIONS_PRESENT
using std::conjunction;
using std::disjunction;
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -14,4 +14,4 @@
limitations under the License.
*/

#include "../oneapi/tbb/blocked_rangeNd.h"
#include "../oneapi/tbb/blocked_nd_range.h"
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 0 additions & 3 deletions test/common/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -160,18 +159,18 @@ int MakeInt(int i) { return i; }

template<unsigned int DimAmount>
void SerialTest() {
static_assert((oneapi::tbb::blocked_rangeNd<int, DimAmount>::ndims() == oneapi::tbb::blocked_rangeNd<AbstractValueType, DimAmount>::ndims()),
static_assert((oneapi::tbb::blocked_nd_range<int, DimAmount>::dim_count() == oneapi::tbb::blocked_nd_range<AbstractValueType, DimAmount>::dim_count()),
"different amount of dimensions");

using range_t = oneapi::tbb::blocked_rangeNd<AbstractValueType, DimAmount>;
using range_t = oneapi::tbb::blocked_nd_range<AbstractValueType, DimAmount>;
using utils_t = range_utils<range_t, DimAmount>;

// Generate empty range
range_t r = utils_t::make_range(0, true, &MakeAbstractValue, oneapi::tbb::detail::make_index_sequence<DimAmount>());

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));
Expand All @@ -190,7 +189,7 @@ template<> void SerialTest<0>() {}

template<unsigned int DimAmount>
void ParallelTest() {
using range_t = oneapi::tbb::blocked_rangeNd<int, DimAmount>;
using range_t = oneapi::tbb::blocked_nd_range<int, DimAmount>;
using utils_t = range_utils<range_t, DimAmount>;

// Max size is 1 << 20 - 1 bytes
Expand All @@ -210,43 +209,60 @@ 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<int, 1>{ { 0,13,3 } };
oneapi::tbb::blocked_nd_range<int, 1>{ { 0,13,3 } };

oneapi::tbb::blocked_rangeNd<int, 1>{ oneapi::tbb::blocked_range<int>{ 0,13,3 } };
oneapi::tbb::blocked_nd_range<int, 1>{ oneapi::tbb::blocked_range<int>{ 0,13,3 } };

oneapi::tbb::blocked_rangeNd<int, 2>(oneapi::tbb::blocked_range<int>(-8923, 8884, 13), oneapi::tbb::blocked_range<int>(-8923, 5, 13));
oneapi::tbb::blocked_nd_range<int, 2>(oneapi::tbb::blocked_range<int>(-8923, 8884, 13), oneapi::tbb::blocked_range<int>(-8923, 5, 13));

oneapi::tbb::blocked_rangeNd<int, 2>({ -8923, 8884, 13 }, { -8923, 8884, 13 });
oneapi::tbb::blocked_nd_range<int, 2>({ -8923, 8884, 13 }, { -8923, 8884, 13 });

oneapi::tbb::blocked_range<int> r1(0, 13);

oneapi::tbb::blocked_range<int> r2(-12, 23);

oneapi::tbb::blocked_rangeNd<int, 2>({ { -8923, 8884, 13 }, r1});
oneapi::tbb::blocked_nd_range<int, 2>({ { -8923, 8884, 13 }, r1});

oneapi::tbb::blocked_rangeNd<int, 2>({ r2, r1 });
oneapi::tbb::blocked_nd_range<int, 2>({ r2, r1 });

oneapi::tbb::blocked_rangeNd<int, 2>(r1, r2);
oneapi::tbb::blocked_nd_range<int, 2>(r1, r2);

oneapi::tbb::blocked_rangeNd<AbstractValueType, 4>({ MakeAbstractValue(-3), MakeAbstractValue(13), 8 },
int sizes[] = {174, 39, 2481, 93};
oneapi::tbb::blocked_nd_range<int, 4> rNd_1(sizes, /*grainsize*/7);

oneapi::tbb::blocked_nd_range<int, 4> rNd_2({174, 39, 2481, 93}, /*grainsize*/11);

for (unsigned i = 0; i < rNd_1.dim_count(); ++i) {
oneapi::tbb::blocked_nd_range<int, 4>::dim_range_type dim1 = rNd_1.dim(i);
oneapi::tbb::blocked_nd_range<int, 4>::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<AbstractValueType, 4>({ MakeAbstractValue(-3), MakeAbstractValue(13), 8 },
{ MakeAbstractValue(-53), MakeAbstractValue(23), 2 },
{ MakeAbstractValue(-23), MakeAbstractValue(33), 1 },
{ MakeAbstractValue(-13), MakeAbstractValue(43), 7 });
}

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<N>();
}

#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() ) {
Expand All @@ -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<int, 2> original{{0, 100}, {0, 100}};
oneapi::tbb::blocked_rangeNd<int, 2> first(original);
TEST_CASE("blocked_nd_range proportional splitting") {
oneapi::tbb::blocked_nd_range<int, 2> original{{0, 100}, {0, 100}};
oneapi::tbb::blocked_nd_range<int, 2> first(original);
oneapi::tbb::proportional_split ps(3, 1);
oneapi::tbb::blocked_rangeNd<int, 2> second(first, ps);
oneapi::tbb::blocked_nd_range<int, 2> second(first, ps);

int expected_first_end = static_cast<int>(
original.dim(0).begin() + ps.left() * (original.dim(0).end() - original.dim(0).begin()) / (ps.left() + ps.right())
Expand Down
Loading
Loading