xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/parallel/omp_loop.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
136ac495dSmrg // -*- C++ -*-
236ac495dSmrg 
3*8feb0f0bSmrg // Copyright (C) 2007-2020 Free Software Foundation, Inc.
436ac495dSmrg //
536ac495dSmrg // This file is part of the GNU ISO C++ Library.  This library is free
636ac495dSmrg // software; you can redistribute it and/or modify it under the terms
736ac495dSmrg // of the GNU General Public License as published by the Free Software
836ac495dSmrg // Foundation; either version 3, or (at your option) any later
936ac495dSmrg // version.
1036ac495dSmrg 
1136ac495dSmrg // This library is distributed in the hope that it will be useful, but
1236ac495dSmrg // WITHOUT ANY WARRANTY; without even the implied warranty of
1336ac495dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1436ac495dSmrg // General Public License for more details.
1536ac495dSmrg 
1636ac495dSmrg // Under Section 7 of GPL version 3, you are granted additional
1736ac495dSmrg // permissions described in the GCC Runtime Library Exception, version
1836ac495dSmrg // 3.1, as published by the Free Software Foundation.
1936ac495dSmrg 
2036ac495dSmrg // You should have received a copy of the GNU General Public License and
2136ac495dSmrg // a copy of the GCC Runtime Library Exception along with this program;
2236ac495dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2336ac495dSmrg // <http://www.gnu.org/licenses/>.
2436ac495dSmrg 
2536ac495dSmrg /** @file parallel/omp_loop.h
2636ac495dSmrg  *  @brief Parallelization of embarrassingly parallel execution by
2736ac495dSmrg  *  means of an OpenMP for loop.
2836ac495dSmrg  *  This file is a GNU parallel extension to the Standard C++ Library.
2936ac495dSmrg  */
3036ac495dSmrg 
3136ac495dSmrg // Written by Felix Putze.
3236ac495dSmrg 
3336ac495dSmrg #ifndef _GLIBCXX_PARALLEL_OMP_LOOP_H
3436ac495dSmrg #define _GLIBCXX_PARALLEL_OMP_LOOP_H 1
3536ac495dSmrg 
3636ac495dSmrg #include <omp.h>
3736ac495dSmrg 
3836ac495dSmrg #include <parallel/settings.h>
3936ac495dSmrg #include <parallel/basic_iterator.h>
4036ac495dSmrg #include <parallel/base.h>
4136ac495dSmrg 
4236ac495dSmrg namespace __gnu_parallel
4336ac495dSmrg {
4436ac495dSmrg   /** @brief Embarrassingly parallel algorithm for random access
4536ac495dSmrg    * iterators, using an OpenMP for loop.
4636ac495dSmrg    *
4736ac495dSmrg    *  @param __begin Begin iterator of element sequence.
4836ac495dSmrg    *  @param __end End iterator of element sequence.
4936ac495dSmrg    *  @param __o User-supplied functor (comparator, predicate, adding
5036ac495dSmrg    *  functor, etc.).
5136ac495dSmrg    *  @param __f Functor to @a process an element with __op (depends on
5236ac495dSmrg    *  desired functionality, e. g. for std::for_each(), ...).
5336ac495dSmrg    *  @param __r Functor to @a add a single __result to the already
5436ac495dSmrg    *  processed elements (depends on functionality).
5536ac495dSmrg    *  @param __base Base value for reduction.
5636ac495dSmrg    *  @param __output Pointer to position where final result is written to
5736ac495dSmrg    *  @param __bound Maximum number of elements processed (e. g. for
5836ac495dSmrg    *  std::count_n()).
5936ac495dSmrg    *  @return User-supplied functor (that may contain a part of the result).
6036ac495dSmrg    */
6136ac495dSmrg   template<typename _RAIter,
6236ac495dSmrg 	   typename _Op,
6336ac495dSmrg 	   typename _Fu,
6436ac495dSmrg 	   typename _Red,
6536ac495dSmrg 	   typename _Result>
6636ac495dSmrg     _Op
__for_each_template_random_access_omp_loop(_RAIter __begin,_RAIter __end,_Op __o,_Fu & __f,_Red __r,_Result __base,_Result & __output,typename std::iterator_traits<_RAIter>::difference_type __bound)6736ac495dSmrg     __for_each_template_random_access_omp_loop(_RAIter __begin, _RAIter __end,
6836ac495dSmrg 					       _Op __o, _Fu& __f, _Red __r,
6936ac495dSmrg 					       _Result __base,
7036ac495dSmrg 					       _Result& __output,
7136ac495dSmrg       typename std::iterator_traits<_RAIter>::difference_type __bound)
7236ac495dSmrg     {
7336ac495dSmrg       typedef typename std::iterator_traits<_RAIter>::difference_type
7436ac495dSmrg         _DifferenceType;
7536ac495dSmrg 
7636ac495dSmrg       _DifferenceType __length = __end - __begin;
7736ac495dSmrg       _ThreadIndex __num_threads = __gnu_parallel::min<_DifferenceType>
7836ac495dSmrg 	(__get_max_threads(), __length);
7936ac495dSmrg 
8036ac495dSmrg       _Result *__thread_results;
8136ac495dSmrg 
8236ac495dSmrg #     pragma omp parallel num_threads(__num_threads)
8336ac495dSmrg       {
8436ac495dSmrg #       pragma omp single
8536ac495dSmrg 	{
8636ac495dSmrg 	  __num_threads = omp_get_num_threads();
8736ac495dSmrg 	  __thread_results = new _Result[__num_threads];
8836ac495dSmrg 
8936ac495dSmrg 	  for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
9036ac495dSmrg 	    __thread_results[__i] = _Result();
9136ac495dSmrg 	}
9236ac495dSmrg 
9336ac495dSmrg         _ThreadIndex __iam = omp_get_thread_num();
9436ac495dSmrg 
9536ac495dSmrg #pragma omp for schedule(dynamic, _Settings::get().workstealing_chunk_size)
9636ac495dSmrg         for (_DifferenceType __pos = 0; __pos < __length; ++__pos)
9736ac495dSmrg           __thread_results[__iam] = __r(__thread_results[__iam],
9836ac495dSmrg 					__f(__o, __begin+__pos));
9936ac495dSmrg       } //parallel
10036ac495dSmrg 
10136ac495dSmrg       for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
10236ac495dSmrg         __output = __r(__output, __thread_results[__i]);
10336ac495dSmrg 
10436ac495dSmrg       delete [] __thread_results;
10536ac495dSmrg 
10636ac495dSmrg       // Points to last element processed (needed as return value for
10736ac495dSmrg       // some algorithms like transform).
10836ac495dSmrg       __f._M_finish_iterator = __begin + __length;
10936ac495dSmrg 
11036ac495dSmrg       return __o;
11136ac495dSmrg     }
11236ac495dSmrg 
11336ac495dSmrg } // end namespace
11436ac495dSmrg 
11536ac495dSmrg #endif /* _GLIBCXX_PARALLEL_OMP_LOOP_H */
116