12#ifndef _TPF_PARALLEL_HPP
13#define _TPF_PARALLEL_HPP
20 #if _MSVC_LANG < 201703L
21 #error This libary requires C++17 Standard (Visual Studio 2017).
25 #if __cplusplus < 201703
26 #error This library requires C++17 Standard (GNU g++ version 8.0 or clang++ version 8.0 above)
31#ifndef TBB_SUPPRESS_DEPRECATED_MESSAGES
32 #define TBB_SUPPRESS_DEPRECATED_MESSAGES 1
35#if !defined(DEBUGGING_MODE)
37 #define DEBUGGING_MODE 1
38 #elif defined(TBB_USE_DEBUG)
40 #define DEBUGGING_MODE 1
42 #define DEBUGGING_MODE 0
45 #define DEBUGGING_MODE 0
49#ifndef LIB_INTERNAL_PutDebugMessageAndExit
50 #define LIB_INTERNAL_PutDebugMessageAndExit(error_msg) \
51 { std::cerr<<"File name ["<<__FILE__<< "]\n" \
52 << "Line " << __LINE__ << " : " << error_msg; \
56#ifndef Tpf_PutDebugMessageAndExit
57 #define Tpf_PutDebugMessageAndExit(error_msg) LIB_INTERNAL_PutDebugMessageAndExit(error_msg)
115 #ifdef __cpp_lib_hardware_interference_size
116 inline constexpr auto cache_line_size = std::hardware_constructive_interference_size;
122 {
return __STDCPP_DEFAULT_NEW_ALIGNMENT__; }
124 template<
typename ElementType,
typename Operation>
127 ElementType old_value = atom;
128 ElementType new_value = opr(old_value);
130 while(!atom.compare_exchange_strong(old_value, new_value))
133 new_value = opr(old_value);
137 #ifndef _TPF_ITERATOR
138 #define _TPF_ITERATOR
140 #ifdef __TBB_iterators_H
142 template <
typename IntType>
148 template <
typename IntType>
150 static_assert(std::numeric_limits<IntType>::is_integer,
"Cannot instantiate counting_iterator with a non-integer type");
202 inline constexpr unsigned long long
207 size_t power_of_2 = 1;
209 while(power_of_2 < n)
216 inline constexpr unsigned long long
221 unsigned long long b = 1;
233 template<
typename Type,
size_t CacheSize = cache_line_size>
248 const Type&
get() const noexcept
250 return this->m_value;
253 operator const Type&()
const noexcept
255 return this->m_value;
258 operator Type&()
noexcept
260 return this->m_value;
265 return &this->m_value;
270 return &this->m_value;
305 template<
typename T,
bool = false>
320 template<
typename Type,
template<
typename,
typename...>
class Container>
322 tbb::cache_aligned_allocator<cache_wrapper_t<Type>>>;
324 template<
typename Type>
327 template<
typename Type,
size_t Size>
329 public std::array<cache_wrapper_t<Type>, Size> { };
331 template<
typename Type,
size_t Size>
334 template<
typename Type>
348 template<
typename Type1,
typename Type2>
351 return (((std::size_t)((
char*)ptr1 - (
char*)ptr2))%
cache_line_size) == 0;
354 template<
typename Type1,
typename Type2>
360 template<
typename Type>
372 inline bool go_parallel(
size_t element_count,
size_t greater_than)
374 return (element_count > std::thread::hardware_concurrency() * greater_than);
377 template<
typename IteratorType>
378 inline bool go_parallel(IteratorType begin, IteratorType end,
size_t greater_than)
380 auto distance = std::distance(begin, end);
381 if(distance < 0) distance = - distance;
383 size_t element_count = (size_t)distance;
389 template<
typename ContainerType>
390 inline bool go_parallel(ContainerType&& container,
size_t greater_than)
392 size_t element_count = container.size();
398 template<
typename IndexType,
typename CallbackType>
399 void for_index(IndexType begin_index, IndexType end_index, CallbackType&& callback,
405 size_t minimum = begin_index < end_index ? begin_index : end_index;
406 size_t maximum = begin_index < end_index ? end_index : begin_index;
409 std::for_each(std::execution::par_unseq,
410 counting_begin, counting_end, std::forward<CallbackType>(callback));
412 std::for_each(counting_begin, counting_end, std::forward<CallbackType>(callback));
415 template<
typename ContainerType,
typename CallbackType>
416 void for_index(ContainerType&& container, CallbackType&& callback,
420 std::forward<CallbackType>(callback), greater_than);
423 template<
typename IndexType,
typename InitType,
424 typename SumupType,
typename HandleParallelType>
425 auto reduce_index(IndexType begin_index, IndexType end_index, InitType&& init_value,
426 SumupType&& sum_up, HandleParallelType&& handle_parallel,
432 size_t minimum = begin_index < end_index ? begin_index : end_index;
433 size_t maximum = begin_index < end_index ? end_index : begin_index;
436 return std::transform_reduce(std::execution::par_unseq,
437 counting_begin, counting_end, std::forward<InitType>(init_value),
438 std::forward<SumupType>(sum_up),
439 std::forward<HandleParallelType>(handle_parallel));
441 return std::transform_reduce(std::execution::seq,
442 counting_begin, counting_end, std::forward<InitType>(init_value),
443 std::forward<SumupType>(sum_up),
444 std::forward<HandleParallelType>(handle_parallel));
447 template<
typename ContainerType,
typename InitType,
448 typename SumupType,
typename HandleParallelType>
450 SumupType&& sum_up, HandleParallelType&& handle_parallel,
454 std::forward<InitType>(init_value),
455 std::forward<SumupType>(sum_up),
456 std::forward<HandleParallelType>(handle_parallel));
friend counting_iterator operator+(difference_type forward, const counting_iterator it)
bool operator==(const counting_iterator &it) const
counting_iterator & operator++()
std::random_access_iterator_tag iterator_category
const IntType & reference
reference operator*() const
counting_iterator operator++(int)
counting_iterator & operator--()
bool operator>=(const counting_iterator &it) const
counting_iterator & operator+=(difference_type forward)
counting_iterator(IntType init)
counting_iterator & operator-=(difference_type backward)
bool operator>(const counting_iterator &it) const
value_type operator[](difference_type i) const
counting_iterator operator--(int)
counting_iterator operator+(difference_type forward) const
bool operator<(const counting_iterator &it) const
bool operator<=(const counting_iterator &it) const
std::make_signed< IntType >::type difference_type
counting_iterator operator-(difference_type backward) const
bool operator!=(const counting_iterator &it) const
difference_type operator-(const counting_iterator &it) const
constexpr decltype(auto) counting_iterator(IndexType idx=IndexType{})
bool operator==(rational< L > const &lhs, rational< R > const &rhs)
string_stream & operator>(string_stream &os, Type &&arg)
string_stream & operator<(string_stream &os, Type &&arg)
constexpr unsigned long long fast_integer_power(unsigned long long x, unsigned long long n)
bool is_cache_aligned(Type *ptr)
constexpr size_t default_alignment()
auto reduce_index(IndexType begin_index, IndexType end_index, InitType &&init_value, SumupType &&sum_up, HandleParallelType &&handle_parallel, size_t greater_than=ConcurrencyLimit)
constexpr unsigned long long least_power_of_2_ge_n(unsigned long long n)
constexpr size_t ForceParallel
constexpr size_t ForceSequential
Container< cache_wrapper_t< Type >, tbb::cache_aligned_allocator< cache_wrapper_t< Type > > > cache_aligned_container_t
constexpr size_t ConcurrencyLimit
void for_index(IndexType begin_index, IndexType end_index, CallbackType &&callback, size_t greater_than=ConcurrencyLimit)
void atomic_operation(std::atomic< ElementType > &atom, Operation &&opr)
cache_aligned_container_t< Type, std::vector > cache_aligned_vector_t
bool go_parallel(size_t element_count, size_t greater_than)
constexpr auto cache_line_size
typename st_cache_wrapper< T, std::is_class_v< T > >::type cache_wrapper_t
types::enable_if_container_type_t< ContainerType< EleType, Types... >, bool > operator!=(const ContainerType< EleType, Types... > &left, const ContainerType< EleType, Types... > &right)
types::enable_if_container_type_t< ContainerType< EleType, Types... >, bool > operator>=(const ContainerType< EleType, Types... > &left, const ContainerType< EleType, Types... > &right)
types::enable_if_container_type_t< ContainerType< EleType, Types... >, bool > operator<=(const ContainerType< EleType, Types... > &left, const ContainerType< EleType, Types... > &right)
Includes subnamespace conversion.
auto minimum(Type_1 a, Type_2 b)
auto maximum(Type_1 a, Type_2 b)
cache_wrapper(cache_wrapper &&)=default
cache_wrapper & operator=(cache_wrapper &&)=default
const Type * operator&() const noexcept
Type * operator&() noexcept
cache_wrapper & operator=(const cache_wrapper &)=default
cache_wrapper(const cache_wrapper &)=default
cache_wrapper(Type v=Type{})
const Type & get() const noexcept
Type functions are implemented.