mirror of
https://github.com/boostorg/container.git
synced 2026-07-06 22:40:48 +02:00
Add BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS option
This commit is contained in:
@@ -45,6 +45,16 @@ segmented_count_dispatch
|
||||
difference_type n = last - first;
|
||||
difference_type count = 0;
|
||||
while(n >= difference_type(4)) {
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
|
||||
count += static_cast<difference_type>(*first == value);
|
||||
++first;
|
||||
count += static_cast<difference_type>(*first == value);
|
||||
++first;
|
||||
count += static_cast<difference_type>(*first == value);
|
||||
++first;
|
||||
count += static_cast<difference_type>(*first == value);
|
||||
++first;
|
||||
#else
|
||||
if(*first == value) ++count;
|
||||
++first;
|
||||
if(*first == value) ++count;
|
||||
@@ -53,20 +63,33 @@ segmented_count_dispatch
|
||||
++first;
|
||||
if(*first == value) ++count;
|
||||
++first;
|
||||
#endif
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
switch(n) {
|
||||
case 3:
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
|
||||
count += static_cast<difference_type>(*first == value);
|
||||
#else
|
||||
if(*first == value) ++count;
|
||||
#endif
|
||||
++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 2:
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
|
||||
count += static_cast<difference_type>(*first == value);
|
||||
#else
|
||||
if(*first == value) ++count;
|
||||
#endif
|
||||
++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 1:
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
|
||||
count += static_cast<difference_type>(*first == value);
|
||||
#else
|
||||
if(*first == value) ++count;
|
||||
#endif
|
||||
++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
@@ -89,7 +112,11 @@ segmented_count_dispatch
|
||||
diff_t n = 0;
|
||||
|
||||
for (; first != last; ++first)
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
|
||||
n += static_cast<diff_t>(*first == value);
|
||||
#else
|
||||
if (*first == value) ++n;
|
||||
#endif
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,16 @@ segmented_count_if_dispatch
|
||||
difference_type n = last - first;
|
||||
difference_type count = 0;
|
||||
while(n >= difference_type(4)) {
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
|
||||
count += static_cast<difference_type>(pred(*first));
|
||||
++first;
|
||||
count += static_cast<difference_type>(pred(*first));
|
||||
++first;
|
||||
count += static_cast<difference_type>(pred(*first));
|
||||
++first;
|
||||
count += static_cast<difference_type>(pred(*first));
|
||||
++first;
|
||||
#else
|
||||
if(pred(*first)) ++count;
|
||||
++first;
|
||||
if(pred(*first)) ++count;
|
||||
@@ -52,20 +62,33 @@ segmented_count_if_dispatch
|
||||
++first;
|
||||
if(pred(*first)) ++count;
|
||||
++first;
|
||||
#endif
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
switch(n) {
|
||||
case 3:
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
|
||||
count += static_cast<difference_type>(pred(*first));
|
||||
#else
|
||||
if(pred(*first)) ++count;
|
||||
#endif
|
||||
++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 2:
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
|
||||
count += static_cast<difference_type>(pred(*first));
|
||||
#else
|
||||
if(pred(*first)) ++count;
|
||||
#endif
|
||||
++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 1:
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
|
||||
count += static_cast<difference_type>(pred(*first));
|
||||
#else
|
||||
if(pred(*first)) ++count;
|
||||
#endif
|
||||
++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
@@ -87,7 +110,11 @@ segmented_count_if_dispatch
|
||||
diff_t n = 0;
|
||||
|
||||
for (; first != last; ++first)
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
|
||||
n += static_cast<diff_t>(pred(*first));
|
||||
#else
|
||||
if (pred(*first)) ++n;
|
||||
#endif
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@@ -381,10 +381,28 @@ struct deepest_local_iterator
|
||||
|
||||
//#define BOOST_CONTAINER_DISABLE_MULTI_SEGMENTED_ALGO
|
||||
|
||||
// When defined, segmented algorithms that have a dual random-access fast path
|
||||
// (e.g. segmented_copy_if_dst_bounded) will not attempt to detect whether the
|
||||
// remaining source range fits the destination capacity and will always take the
|
||||
// fast path when both iterators are random-access. This is useful for benchmarking
|
||||
// the advantage of the dual-RA optimisation in isolation.
|
||||
//
|
||||
//#define BOOST_CONTAINER_SEGMENTED_DISABLE_DUAL_RA_OPTIMIZATION
|
||||
|
||||
#if !defined(BOOST_CONTAINER_SEGMENTED_DISABLE_DUAL_RA_OPTIMIZATION)
|
||||
#define BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION
|
||||
#endif
|
||||
|
||||
// When defined, segmented algorithms that count elements (e.g. segmented_count,
|
||||
// segmented_count_if) will use a branchless counting strategy in their
|
||||
// innermost loops, incrementing the count by the boolean result of the
|
||||
// predicate rather than testing the predicate result in a branch and conditionally
|
||||
// incrementing. This can improve performance on some platforms by avoiding branch mispredictions,
|
||||
// at the cost of potentially increased instruction count and/or reduced vectorization opportunities.
|
||||
//
|
||||
// However, the optimal strategy is highly platform- and algorithm-specific, so this is disabled by default.
|
||||
// There are regressions on some algorithms and platforms when this is enabled, and the performance impact
|
||||
// varies widely across different scenarios.
|
||||
//
|
||||
//#define BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS
|
||||
|
||||
#endif // BOOST_CONTAINER_EXPERIMENTAL_SEGMENTED_ITERATOR_TRAITS_HPP
|
||||
|
||||
Reference in New Issue
Block a user