opm-grid
createThreadIterators.hpp
1 /*
2  Copyright 2025 Equinor ASA.
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef OPM_CREATETHREADITERATORS_HEADER_INCLUDED
21 #define OPM_CREATETHREADITERATORS_HEADER_INCLUDED
22 
23 #include <algorithm>
24 #include <cassert>
25 #include <stdexcept>
26 #include <string>
27 #include <vector>
28 
29 namespace Opm
30 {
31 
47  template <class Range>
48  auto createChunkIterators(const Range& r,
49  const std::size_t num_elem,
50  const std::size_t num_chunks)
51  {
52  if (num_chunks < 1) {
53  throw std::logic_error("createChunkIterators() must create at least one chunk.");
54  }
55  std::vector<decltype(std::begin(r))> chunk_iterators;
56  auto it = std::begin(r);
57  const auto end = std::end(r);
58  if (num_chunks == 1) {
59  chunk_iterators.push_back(it);
60  chunk_iterators.push_back(end);
61  } else {
62  const auto chunk_size = std::max(num_elem / num_chunks, 1ul);
63  chunk_iterators.reserve(num_chunks + 1);
64  // Push evenly spaced iterators for the beginning of each chunk.
65  // We do this a number of times equal to the number of chunks.
66  for (std::size_t count = 0, num_pushed = 0; it != end; ++it, ++count) {
67  if (count % chunk_size == 0) {
68  chunk_iterators.push_back(it);
69  ++num_pushed;
70  if (num_pushed == num_chunks) {
71  // This break means that the last chunk may be bigger
72  // then the other ones.
73  break;
74  }
75  }
76  }
77  // Push sufficiently many end iterators to make the required number of chunks,
78  // there may be more than one (yielding empty chunks) if num_chunks > num_elem.
79  for (std::size_t extra = chunk_iterators.size(); extra < num_chunks + 1; ++extra) {
80  chunk_iterators.push_back(end);
81  }
82  assert(chunk_iterators.size() == num_chunks + 1);
83  }
84  return chunk_iterators;
85  }
86 
87 
105  template <class Range>
106  auto createThreadIterators(const Range& r,
107  const std::size_t num_elem,
108  const std::size_t num_threads,
109  const std::size_t max_chunk_size,
110  int& chunk_size)
111  {
112  if (num_threads < 1) {
113  throw std::logic_error("createThreadIterators() called with num_threads arguments = "
114  + std::to_string(num_threads));
115  }
116  std::vector<decltype(std::begin(r))> chunk_iterators;
117  auto it = std::begin(r);
118  const auto end = std::end(r);
119  if (num_threads == 1) {
120  chunk_iterators.push_back(it);
121  chunk_iterators.push_back(end);
122  } else {
123  chunk_size = static_cast<int>(std::clamp(num_elem / num_threads, 1ul, max_chunk_size));
124  chunk_iterators.reserve(num_elem / chunk_size + 2);
125  for (int count = 0; it != end; ++it, ++count) {
126  if (count % chunk_size == 0) {
127  chunk_iterators.push_back(it);
128  }
129  }
130  chunk_iterators.push_back(end);
131  }
132  return chunk_iterators;
133  }
134 
135 
138  template <class GridView>
139  auto createThreadIterators(const GridView& gv,
140  const std::size_t num_threads,
141  const std::size_t max_chunk_size,
142  int& chunk_size)
143  {
144  return createThreadIterators(elements(gv),
145  gv.size(0),
146  num_threads,
147  max_chunk_size,
148  chunk_size);
149  }
150 
151 } // namespace Opm
152 
153 #endif // OPM_CREATETHREADITERATORS_HEADER_INCLUDED
auto createChunkIterators(const Range &r, const std::size_t num_elem, const std::size_t num_chunks)
Create a vector containing a spread of iterators into the elements of the range, to facilitate for ex...
Definition: createThreadIterators.hpp:48
Holds the implementation of the CpGrid as a pimple.
Definition: CellQuadrature.cpp:71
auto createThreadIterators(const Range &r, const std::size_t num_elem, const std::size_t num_threads, const std::size_t max_chunk_size, int &chunk_size)
Create a vector containing a spread of iterators into the elements of the range, to facilitate for ex...
Definition: createThreadIterators.hpp:106