summaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/parallel/find.h
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include/parallel/find.h')
-rw-r--r--libstdc++-v3/include/parallel/find.h458
1 files changed, 253 insertions, 205 deletions
diff --git a/libstdc++-v3/include/parallel/find.h b/libstdc++-v3/include/parallel/find.h
index bc89fa570e5..2a5b22c629f 100644
--- a/libstdc++-v3/include/parallel/find.h
+++ b/libstdc++-v3/include/parallel/find.h
@@ -10,7 +10,7 @@
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURstartE. See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public License
@@ -48,50 +48,66 @@
namespace __gnu_parallel
{
- /**
- * @brief Parallel std::find, switch for different algorithms.
- * @param begin1 Begin iterator of first sequence.
- * @param end1 End iterator of first sequence.
- * @param begin2 Begin iterator of second sequence. Must have same
- * length as first sequence.
- * @param pred Find predicate.
- * @param selector Functionality (e. g. std::find_if (), std::equal(),...)
- * @return Place of finding in both sequences.
- */
- template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Pred, typename Selector>
+/**
+ * @brief Parallel std::find, switch for different algorithms.
+ * @param begin1 Begin iterator of first sequence.
+ * @param end1 End iterator of first sequence.
+ * @param begin2 Begin iterator of second sequence. Must have same
+ * length as first sequence.
+ * @param pred Find predicate.
+ * @param selector Functionality (e. g. std::find_if (), std::equal(),...)
+ * @return Place of finding in both sequences.
+ */
+template<
+ typename RandomAccessIterator1,
+ typename RandomAccessIterator2,
+ typename Pred,
+ typename Selector>
std::pair<RandomAccessIterator1, RandomAccessIterator2>
find_template(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
- RandomAccessIterator2 begin2, Pred pred, Selector selector)
+ RandomAccessIterator2 begin2, Pred pred, Selector selector)
{
switch (Settings::find_distribution)
{
case Settings::GROWING_BLOCKS:
- return find_template(begin1, end1, begin2, pred, selector, growing_blocks_tag());
+ return find_template(begin1, end1, begin2, pred, selector,
+ growing_blocks_tag());
case Settings::CONSTANT_SIZE_BLOCKS:
- return find_template(begin1, end1, begin2, pred, selector, constant_size_blocks_tag());
+ return find_template(begin1, end1, begin2, pred, selector,
+ constant_size_blocks_tag());
case Settings::EQUAL_SPLIT:
- return find_template(begin1, end1, begin2, pred, selector, equal_split_tag());
+ return find_template(begin1, end1, begin2, pred, selector,
+ equal_split_tag());
default:
- _GLIBCXX_PARALLEL_ASSERT(false);
- return std::make_pair(begin1, begin2);
+ _GLIBCXX_PARALLEL_ASSERT(false);
+ return std::make_pair(begin1, begin2);
}
}
#if _GLIBCXX_FIND_EQUAL_SPLIT
- /**
- * @brief Parallel std::find, equal splitting variant.
- * @param begin1 Begin iterator of first sequence.
- * @param end1 End iterator of first sequence.
- * @param begin2 Begin iterator of second sequence. Second sequence
- * must have same length as first sequence.
- * @param pred Find predicate.
- * @param selector Functionality (e. g. std::find_if (), std::equal(),...)
- * @return Place of finding in both sequences.
- */
- template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Pred, typename Selector>
+/**
+ * @brief Parallel std::find, equal splitting variant.
+ * @param begin1 Begin iterator of first sequence.
+ * @param end1 End iterator of first sequence.
+ * @param begin2 Begin iterator of second sequence. Second sequence
+ * must have same length as first sequence.
+ * @param pred Find predicate.
+ * @param selector Functionality (e. g. std::find_if (), std::equal(),...)
+ * @return Place of finding in both sequences.
+ */
+template<
+ typename RandomAccessIterator1,
+ typename RandomAccessIterator2,
+ typename Pred,
+ typename Selector>
std::pair<RandomAccessIterator1, RandomAccessIterator2>
- find_template(RandomAccessIterator1 begin1, RandomAccessIterator1 end1, RandomAccessIterator2 begin2, Pred pred, Selector selector, equal_split_tag)
+ find_template(RandomAccessIterator1 begin1,
+ RandomAccessIterator1 end1,
+ RandomAccessIterator2 begin2,
+ Pred pred,
+ Selector selector,
+ equal_split_tag)
{
_GLIBCXX_CALL(end1 - begin1)
@@ -100,79 +116,89 @@ namespace __gnu_parallel
typedef typename traits_type::value_type value_type;
difference_type length = end1 - begin1;
-
difference_type result = length;
+ difference_type* borders;
- const thread_index_t num_threads = get_max_threads();
omp_lock_t result_lock;
omp_init_lock(&result_lock);
- difference_type* borders = static_cast<difference_type*>(__builtin_alloca(sizeof(difference_type) * (num_threads + 1)));
-
- equally_split(length, num_threads, borders);
-
-#pragma omp parallel shared(result) num_threads(num_threads)
- {
- int iam = omp_get_thread_num();
- difference_type pos = borders[iam], limit = borders[iam + 1];
-
- RandomAccessIterator1 i1 = begin1 + pos;
- RandomAccessIterator2 i2 = begin2 + pos;
- for (; pos < limit; pos++)
- {
-#pragma omp flush(result)
- // Result has been set to something lower.
- if (result < pos)
- break;
-
- if (selector(i1, i2, pred))
- {
- omp_set_lock(&result_lock);
- if (result > pos)
- result = pos;
- omp_unset_lock(&result_lock);
+ thread_index_t num_threads = get_max_threads();
+# pragma omp parallel num_threads(num_threads)
+ {
+# pragma omp single
+ {
+ num_threads = omp_get_num_threads();
+ borders = new difference_type[num_threads + 1];
+ equally_split(length, num_threads, borders);
+ } //single
+
+ thread_index_t iam = omp_get_thread_num();
+ difference_type start = borders[iam], stop = borders[iam + 1];
+
+ RandomAccessIterator1 i1 = begin1 + start;
+ RandomAccessIterator2 i2 = begin2 + start;
+ for (difference_type pos = start; pos < stop; ++pos)
+ {
+ #pragma omp flush(result)
+ // Result has been set to something lower.
+ if (result < pos)
break;
- }
- i1++;
- i2++;
- }
- }
+
+ if (selector(i1, i2, pred))
+ {
+ omp_set_lock(&result_lock);
+ if (pos < result)
+ result = pos;
+ omp_unset_lock(&result_lock);
+ break;
+ }
+ ++i1;
+ ++i2;
+ }
+ } //parallel
omp_destroy_lock(&result_lock);
- return std::pair<RandomAccessIterator1, RandomAccessIterator2>(begin1 + result, begin2 + result);
+ delete[] borders;
+
+ return std::pair<RandomAccessIterator1, RandomAccessIterator2>(
+ begin1 + result, begin2 + result);
}
#endif
#if _GLIBCXX_FIND_GROWING_BLOCKS
- /**
- * @brief Parallel std::find, growing block size variant.
- * @param begin1 Begin iterator of first sequence.
- * @param end1 End iterator of first sequence.
- * @param begin2 Begin iterator of second sequence. Second sequence
- * must have same length as first sequence.
- * @param pred Find predicate.
- * @param selector Functionality (e. g. std::find_if (), std::equal(),...)
- * @return Place of finding in both sequences.
- * @see __gnu_parallel::Settings::find_sequential_search_size
- * @see __gnu_parallel::Settings::find_initial_block_size
- * @see __gnu_parallel::Settings::find_maximum_block_size
- * @see __gnu_parallel::Settings::find_increasing_factor
- *
- * There are two main differences between the growing blocks and
- * the constant-size blocks variants.
- * 1. For GB, the block size grows; for CSB, the block size is fixed.
-
- * 2. For GB, the blocks are allocated dynamically;
- * for CSB, the blocks are allocated in a predetermined manner,
- * namely spacial round-robin.
- */
- template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Pred, typename Selector>
+/**
+ * @brief Parallel std::find, growing block size variant.
+ * @param begin1 Begin iterator of first sequence.
+ * @param end1 End iterator of first sequence.
+ * @param begin2 Begin iterator of second sequence. Second sequence
+ * must have same length as first sequence.
+ * @param pred Find predicate.
+ * @param selector Functionality (e. g. std::find_if (), std::equal(),...)
+ * @return Place of finding in both sequences.
+ * @see __gnu_parallel::Settings::find_sequential_search_size
+ * @see __gnu_parallel::Settings::find_initial_block_size
+ * @see __gnu_parallel::Settings::find_maximum_block_size
+ * @see __gnu_parallel::Settings::find_increasing_factor
+ *
+ * There are two main differences between the growing blocks and
+ * the constant-size blocks variants.
+ * 1. For GB, the block size grows; for CSB, the block size is fixed.
+
+ * 2. For GB, the blocks are allocated dynamically;
+ * for CSB, the blocks are allocated in a predetermined manner,
+ * namely spacial round-robin.
+ */
+template<
+ typename RandomAccessIterator1,
+ typename RandomAccessIterator2,
+ typename Pred,
+ typename Selector>
std::pair<RandomAccessIterator1, RandomAccessIterator2>
find_template(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
- RandomAccessIterator2 begin2, Pred pred, Selector selector,
- growing_blocks_tag)
+ RandomAccessIterator2 begin2, Pred pred, Selector selector,
+ growing_blocks_tag)
{
_GLIBCXX_CALL(end1 - begin1)
@@ -182,101 +208,118 @@ namespace __gnu_parallel
difference_type length = end1 - begin1;
- difference_type sequential_search_size = std::min<difference_type>(length, Settings::find_sequential_search_size);
+ difference_type sequential_search_size = std::min<difference_type>(
+ length, Settings::find_sequential_search_size);
// Try it sequentially first.
std::pair<RandomAccessIterator1, RandomAccessIterator2> find_seq_result =
- selector.sequential_algorithm(begin1, begin1 + sequential_search_size, begin2, pred);
+ selector.sequential_algorithm(
+ begin1, begin1 + sequential_search_size, begin2, pred);
if (find_seq_result.first != (begin1 + sequential_search_size))
return find_seq_result;
// Index of beginning of next free block (after sequential find).
- difference_type next_block_pos = sequential_search_size;
+ difference_type next_block_start = sequential_search_size;
difference_type result = length;
- const thread_index_t num_threads = get_max_threads();
omp_lock_t result_lock;
omp_init_lock(&result_lock);
-#pragma omp parallel shared(result) num_threads(num_threads)
- {
- // Not within first k elements -> start parallel.
- thread_index_t iam = omp_get_thread_num();
-
- difference_type block_size = Settings::find_initial_block_size;
- difference_type start = fetch_and_add<difference_type>(&next_block_pos, block_size);
-
- // Get new block, update pointer to next block.
- difference_type stop = std::min<difference_type>(length, start + block_size);
-
- std::pair<RandomAccessIterator1, RandomAccessIterator2> local_result;
-
- while (start < length)
- {
-#pragma omp flush(result)
- // Get new value of result.
- if (result < start)
- {
- // No chance to find first element.
- break;
- }
-
- local_result = selector.sequential_algorithm(begin1 + start, begin1 + stop, begin2 + start, pred);
- if (local_result.first != (begin1 + stop))
- {
- omp_set_lock(&result_lock);
- if ((local_result.first - begin1) < result)
- {
- result = local_result.first - begin1;
-
- // Result cannot be in future blocks, stop algorithm.
- fetch_and_add<difference_type>(&next_block_pos, length);
- }
- omp_unset_lock(&result_lock);
- }
-
- block_size = std::min<difference_type>(block_size * Settings::find_increasing_factor, Settings::find_maximum_block_size);
-
- // Get new block, update pointer to next block.
- start = fetch_and_add<difference_type>(&next_block_pos, block_size);
- stop = (length < (start + block_size)) ? length : (start + block_size);
- }
- }
+ thread_index_t num_threads = get_max_threads();
+# pragma omp parallel shared(result) num_threads(num_threads)
+ {
+# pragma omp single
+ num_threads = omp_get_num_threads();
+
+ // Not within first k elements -> start parallel.
+ thread_index_t iam = omp_get_thread_num();
+
+ difference_type block_size = Settings::find_initial_block_size;
+ difference_type start =
+ fetch_and_add<difference_type>(&next_block_start, block_size);
+
+ // Get new block, update pointer to next block.
+ difference_type stop =
+ std::min<difference_type>(length, start + block_size);
+
+ std::pair<RandomAccessIterator1, RandomAccessIterator2> local_result;
+
+ while (start < length)
+ {
+# pragma omp flush(result)
+ // Get new value of result.
+ if (result < start)
+ {
+ // No chance to find first element.
+ break;
+ }
+
+ local_result = selector.sequential_algorithm(
+ begin1 + start, begin1 + stop, begin2 + start, pred);
+ if (local_result.first != (begin1 + stop))
+ {
+ omp_set_lock(&result_lock);
+ if ((local_result.first - begin1) < result)
+ {
+ result = local_result.first - begin1;
+
+ // Result cannot be in future blocks, stop algorithm.
+ fetch_and_add<difference_type>(&next_block_start, length);
+ }
+ omp_unset_lock(&result_lock);
+ }
+
+ block_size = std::min<difference_type>(
+ block_size * Settings::find_increasing_factor,
+ Settings::find_maximum_block_size);
+
+ // Get new block, update pointer to next block.
+ start =
+ fetch_and_add<difference_type>(&next_block_start, block_size);
+ stop = (length < (start + block_size)) ?
+ length : (start + block_size);
+ }
+ } //parallel
omp_destroy_lock(&result_lock);
// Return iterator on found element.
- return std::pair<RandomAccessIterator1, RandomAccessIterator2>(begin1 + result, begin2 + result);
+ return std::pair<RandomAccessIterator1, RandomAccessIterator2>(
+ begin1 + result, begin2 + result);
}
#endif
#if _GLIBCXX_FIND_CONSTANT_SIZE_BLOCKS
- /**
- * @brief Parallel std::find, constant block size variant.
- * @param begin1 Begin iterator of first sequence.
- * @param end1 End iterator of first sequence.
- * @param begin2 Begin iterator of second sequence. Second sequence
- * must have same length as first sequence.
- * @param pred Find predicate.
- * @param selector Functionality (e. g. std::find_if (), std::equal(),...)
- * @return Place of finding in both sequences.
- * @see __gnu_parallel::Settings::find_sequential_search_size
- * @see __gnu_parallel::Settings::find_block_size
- * There are two main differences between the growing blocks and the
- * constant-size blocks variants.
- * 1. For GB, the block size grows; for CSB, the block size is fixed.
- * 2. For GB, the blocks are allocated dynamically; for CSB, the
- * blocks are allocated in a predetermined manner, namely spacial
- * round-robin.
- */
- template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Pred, typename Selector>
+/**
+ * @brief Parallel std::find, constant block size variant.
+ * @param begin1 Begin iterator of first sequence.
+ * @param end1 End iterator of first sequence.
+ * @param begin2 Begin iterator of second sequence. Second sequence
+ * must have same length as first sequence.
+ * @param pred Find predicate.
+ * @param selector Functionality (e. g. std::find_if (), std::equal(),...)
+ * @return Place of finding in both sequences.
+ * @see __gnu_parallel::Settings::find_sequential_search_size
+ * @see __gnu_parallel::Settings::find_block_size
+ * There are two main differences between the growing blocks and the
+ * constant-size blocks variants.
+ * 1. For GB, the block size grows; for CSB, the block size is fixed.
+ * 2. For GB, the blocks are allocated dynamically; for CSB, the
+ * blocks are allocated in a predetermined manner, namely spacial
+ * round-robin.
+ */
+template<
+ typename RandomAccessIterator1,
+ typename RandomAccessIterator2,
+ typename Pred,
+ typename Selector>
std::pair<RandomAccessIterator1, RandomAccessIterator2>
find_template(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
- RandomAccessIterator2 begin2, Pred pred, Selector selector,
- constant_size_blocks_tag)
+ RandomAccessIterator2 begin2, Pred pred, Selector selector,
+ constant_size_blocks_tag)
{
_GLIBCXX_CALL(end1 - begin1)
typedef std::iterator_traits<RandomAccessIterator1> traits_type;
@@ -285,72 +328,77 @@ namespace __gnu_parallel
difference_type length = end1 - begin1;
- difference_type sequential_search_size = std::min<difference_type>(length, Settings::find_sequential_search_size);
+ difference_type sequential_search_size = std::min<difference_type>(
+ length, Settings::find_sequential_search_size);
// Try it sequentially first.
std::pair<RandomAccessIterator1, RandomAccessIterator2> find_seq_result =
- selector.sequential_algorithm(begin1, begin1 + sequential_search_size, begin2, pred);
+ selector.sequential_algorithm(begin1, begin1 + sequential_search_size,
+ begin2, pred);
if (find_seq_result.first != (begin1 + sequential_search_size))
return find_seq_result;
difference_type result = length;
- const thread_index_t num_threads = get_max_threads();
-
omp_lock_t result_lock;
omp_init_lock(&result_lock);
// Not within first sequential_search_size elements -> start parallel.
-#pragma omp parallel shared(result) num_threads(num_threads)
- {
- thread_index_t iam = omp_get_thread_num();
- difference_type block_size = Settings::find_initial_block_size;
-
- difference_type start, stop;
-
- // First element of thread's current iteration.
- difference_type iteration_start = sequential_search_size;
-
- // Where to work (initialization).
- start = iteration_start + iam * block_size;
- stop = std::min<difference_type>(length, start + block_size);
-
- std::pair<RandomAccessIterator1, RandomAccessIterator2> local_result;
-
- while (start < length)
- {
- // Get new value of result.
-#pragma omp flush(result)
- // No chance to find first element.
- if (result < start)
- break;
-
- local_result = selector.sequential_algorithm(begin1 + start, begin1 + stop, begin2 + start, pred);
- if (local_result.first != (begin1 + stop))
- {
- omp_set_lock(&result_lock);
- if ((local_result.first - begin1) < result)
- result = local_result.first - begin1;
- omp_unset_lock(&result_lock);
- // Will not find better value in its interval.
- break;
- }
-
- iteration_start += num_threads * block_size;
-
- // Where to work.
- start = iteration_start + iam * block_size;
- stop = std::min<difference_type>(length, start + block_size);
- }
- }
+
+ thread_index_t num_threads = get_max_threads();
+# pragma omp parallel shared(result) num_threads(num_threads)
+ {
+# pragma omp single
+ num_threads = omp_get_num_threads();
+
+ thread_index_t iam = omp_get_thread_num();
+ difference_type block_size = Settings::find_initial_block_size;
+
+ // First element of thread's current iteration.
+ difference_type iteration_start = sequential_search_size;
+
+ // Where to work (initialization).
+ difference_type start = iteration_start + iam * block_size;
+ difference_type stop =
+ std::min<difference_type>(length, start + block_size);
+
+ std::pair<RandomAccessIterator1, RandomAccessIterator2> local_result;
+
+ while (start < length)
+ {
+ // Get new value of result.
+# pragma omp flush(result)
+ // No chance to find first element.
+ if (result < start)
+ break;
+ local_result = selector.sequential_algorithm(
+ begin1 + start, begin1 + stop,
+ begin2 + start, pred);
+ if (local_result.first != (begin1 + stop))
+ {
+ omp_set_lock(&result_lock);
+ if ((local_result.first - begin1) < result)
+ result = local_result.first - begin1;
+ omp_unset_lock(&result_lock);
+ // Will not find better value in its interval.
+ break;
+ }
+
+ iteration_start += num_threads * block_size;
+
+ // Where to work.
+ start = iteration_start + iam * block_size;
+ stop = std::min<difference_type>(length, start + block_size);
+ }
+ } //parallel
omp_destroy_lock(&result_lock);
// Return iterator on found element.
- return std::pair<RandomAccessIterator1, RandomAccessIterator2>(begin1 + result, begin2 + result);
+ return std::pair<RandomAccessIterator1, RandomAccessIterator2>(
+ begin1 + result, begin2 + result);
}
#endif
} // end namespace
#endif
-