1 #ifndef DASH__ALGORITHM__MIN_MAX_H__ 2 #define DASH__ALGORITHM__MIN_MAX_H__ 4 #include <dash/internal/Config.h> 6 #include <dash/Allocator.h> 8 #include <dash/algorithm/LocalRange.h> 10 #include <dash/util/Config.h> 11 #include <dash/util/Trace.h> 12 #include <dash/util/UnitLocality.h> 14 #include <dash/internal/Logging.h> 15 #include <dash/iterator/GlobIter.h> 20 #ifdef DASH_ENABLE_OPENMP 46 class Compare = std::less<const ElementType &> >
49 const ElementType * l_range_begin,
51 const ElementType * l_range_end,
54 = std::less<const ElementType &>())
56 #ifdef DASH_ENABLE_OPENMP 57 #define ROUNDUP(T, A) ((T + A - 1) & ~(A - 1)) 59 typedef typename std::decay<ElementType>::type value_t;
63 DASH_LOG_DEBUG(
"dash::min_element",
"thread capacity:", n_threads);
68 auto l_size = l_range_end - l_range_begin;
70 ElementType min_val_l = *l_range_begin;
72 typedef struct min_pos_t { value_t val;
size_t idx; } min_pos;
74 DASH_LOG_TRACE(
"dash::min_element",
"sizeof(min_pos):",
sizeof(min_pos));
78 int align_bytes = uloc.cache_line_size(0);
79 int single_element_sz = ROUNDUP(
sizeof(min_pos), align_bytes);
81 size_t min_vals_t_bytes = single_element_sz * n_threads;
83 auto min_vals_t_raw =
static_cast<uint8_t *
>(
84 hostSpace.allocate(min_vals_t_bytes, align_bytes));
86 DASH_LOG_TRACE(
"dash::min_element",
"min * alloc:", min_vals_t_raw);
88 DASH_LOG_TRACE(
"dash::min_element",
"min * size:", min_vals_t_bytes);
89 DASH_ASSERT_GE(min_vals_t_bytes, n_threads *
sizeof(min_pos),
90 "Aligned buffer of min_pos has insufficient size");
91 DASH_ASSERT_MSG(
nullptr != min_vals_t_raw,
92 "Aligned allocation of min_pos returned nullptr");
99 #pragma omp parallel num_threads(n_threads) private(t_id) 104 t_id = omp_get_thread_num();
105 DASH_LOG_TRACE(
"dash::min_element",
"starting thread", t_id);
106 auto & min_val_t = *(
reinterpret_cast<min_pos *
>(min_vals_t_raw + t_id * single_element_sz));
107 min_val_t.idx = min_idx_l;
108 min_val_t.val = min_val_l;
111 #pragma omp for schedule(static) 112 for (
int i = 0; i < l_size; i++) {
113 const ElementType & val_t = *(l_range_begin + i);
114 if (compare(val_t, min_val_t.val)) {
115 min_val_t.val = val_t;
119 DASH_LOG_TRACE(
"dash::min_element",
"local minimum at thread", t_id,
120 "idx:", min_val_t.idx,
121 "val:", min_val_t.val);
124 min_pos min_pos_l = * (
reinterpret_cast<min_pos *
>(min_vals_t_raw));
126 for (
int t = 1; t < n_threads; t++) {
127 const min_pos & mpt = *(
reinterpret_cast<min_pos *
>(min_vals_t_raw + t * single_element_sz));
128 if (compare(mpt.val, min_pos_l.val)) {
133 hostSpace.deallocate(min_vals_t_raw, min_vals_t_bytes, align_bytes);
135 return (l_range_begin + min_pos_l.idx);
137 #endif // DASH_ENABLE_OPENMP 158 typename GlobInputIt,
159 class Compare = std::less<
160 const typename dash::iterator_traits<GlobInputIt>::value_type &> >
163 const typename std::enable_if<
165 GlobInputIt>::type &
first,
167 const GlobInputIt &last,
169 Compare compare = Compare())
171 typedef typename GlobInputIt::pattern_type pattern_t;
172 typedef typename pattern_t::index_type index_t;
173 typedef typename std::decay<
174 typename dash::iterator_traits<GlobInputIt>::value_type>::type value_t;
178 DASH_LOG_DEBUG(
"dash::min_element >",
179 "empty range, returning last", last);
185 auto & pattern = first.pattern();
186 auto & team = pattern.team();
187 DASH_LOG_DEBUG(
"dash::min_element()",
188 "allocate minarr, size", team.size());
190 auto gi_last = last.gpos();
195 const value_t * lmin =
nullptr;
197 index_t l_idx_lmin = -1;
198 if (local_idx_range.begin == local_idx_range.end) {
200 DASH_LOG_DEBUG(
"dash::min_element",
"local range empty");
202 trace.enter_state(
"local");
206 static_cast<typename GlobInputIt::const_pointer>(first), team.myid());
209 const auto * l_range_begin = lbegin + local_idx_range.begin;
210 const auto * l_range_end = lbegin + local_idx_range.end;
214 if (lmin != l_range_end) {
215 DASH_LOG_TRACE_VAR(
"dash::min_element", *lmin);
217 l_idx_lmin = lmin - lbegin;
220 trace.exit_state(
"local");
222 DASH_LOG_TRACE(
"dash::min_element",
223 "local index of local minimum:", l_idx_lmin);
224 DASH_LOG_TRACE(
"dash::min_element",
225 "waiting for local min of other units");
227 trace.enter_state(
"barrier");
229 trace.exit_state(
"barrier");
236 std::vector<local_min_t> local_min_values(team.size());
240 local_min_t local_min;
241 local_min.value = l_idx_lmin < 0
244 local_min.g_index = l_idx_lmin < 0
246 : pattern.global(l_idx_lmin);
248 DASH_LOG_TRACE(
"dash::min_element",
"sending local minimum: {",
249 "value:", local_min.value,
250 "g.index:", local_min.g_index,
"}");
252 DASH_LOG_TRACE(
"dash::min_element",
"dart_allgather()");
253 trace.enter_state(
"allgather");
257 local_min_values.data(),
262 trace.exit_state(
"allgather");
264 #ifdef DASH_ENABLE_LOGGING 265 for (
int lmin_u = 0; lmin_u < local_min_values.size(); lmin_u++) {
266 auto lmin_entry = local_min_values[lmin_u];
267 DASH_LOG_TRACE(
"dash::min_element",
"dart_allgather >",
269 "value:", lmin_entry.value,
270 "g_index:", lmin_entry.g_index);
275 local_min_values.begin(),
276 local_min_values.end(),
277 [&](
const local_min_t & a,
278 const local_min_t & b) {
281 return (b.g_index < 0 ||
283 compare(a.value, b.value)));
286 if (gmin_elem_it == local_min_values.end()) {
287 DASH_LOG_DEBUG_VAR(
"dash::min_element >", last);
291 auto gi_minimum = gmin_elem_it->g_index;
293 DASH_LOG_TRACE(
"dash::min_element",
294 "min. value:", gmin_elem_it->value,
295 "at unit:", (gmin_elem_it - local_min_values.begin()),
296 "global idx:", gi_minimum);
298 DASH_LOG_TRACE_VAR(
"dash::min_element", gi_minimum);
299 if (gi_minimum < 0 || gi_minimum == gi_last) {
300 DASH_LOG_DEBUG_VAR(
"dash::min_element >", last);
306 auto minimum = (first - first.gpos()) + gi_minimum;
307 DASH_LOG_DEBUG(
"dash::min_element >", minimum,
308 "=", static_cast<value_t>(*minimum));
331 class Compare = std::greater<const typename GlobIter::value_type &> >
338 Compare compare = Compare())
361 template <
class ElementType,
class Compare = std::greater<ElementType &> >
364 const ElementType *first,
366 const ElementType *last,
368 Compare compare = Compare())
376 #endif // DASH__ALGORITHM__MIN_MAX_H__ DASH_CONSTEXPR std::enable_if< std::is_same< typename dash::memory_space_traits< MemSpaceT >::memory_space_layout_tag, memory_space_contiguous >::value, T >::type * local_begin(GlobPtr< T, MemSpaceT > global_begin, dash::team_unit_t unit)
Returns the begin of the local memory portion within a global memory segment.
This class is a simple memory pool which holds allocates elements of size ValueType.
dart_ret_t dart_allgather(const void *sendbuf, void *recvbuf, size_t nelem, dart_datatype_t dtype, dart_team_t team)
DART Equivalent to MPI allgather.
int num_domain_threads()
Number of threads currently available to the active unit.
GlobInputIt min_element(const typename std::enable_if< dash::iterator_traits< GlobInputIt >::is_global_iterator::value, GlobInputIt >::type &first, const GlobInputIt &last, Compare compare=Compare())
Finds an iterator pointing to the element with the smallest value in the range [first,last).
const ElementType * min_element(const ElementType *l_range_begin, const ElementType *l_range_end, Compare compare=std::less< const ElementType &>())
Finds an iterator pointing to the element with the smallest value in the range [first,last).
Iterator on Partitioned Global Address Space.
#define DART_TYPE_BYTE
integral data types
GlobIter max_element(const GlobIter &first, const GlobIter &last, Compare compare=Compare())
Finds an iterator pointing to the element with the greatest value in the range [first,last).
std::enable_if< !GlobInputIter::has_view::value, LocalIndexRange< typename GlobInputIter::pattern_type::index_type >>::type local_index_range(const GlobInputIter &first, const GlobInputIter &last)
Resolves the local index range between global iterators.
Wrapper of a single dart_unit_locality_t object.