14#include "arcane/utils/TraceAccessor.h"
15#include "arcane/utils/FatalErrorException.h"
17#include "arcane/core/IParallelMng.h"
18#include "arcane/core/parallel/BitonicSort.h"
29template <
typename KeyType,
typename KeyTypeTraits> BitonicSort<KeyType, KeyTypeTraits>::
30BitonicSort(IParallelMng* parallel_mng)
31: TraceAccessor(parallel_mng->traceMng())
32, m_parallel_mng(parallel_mng)
39template <
typename KeyType,
typename KeyTypeTraits>
void BitonicSort<KeyType, KeyTypeTraits>::
40_init(ConstArrayView<KeyType> keys)
42 m_init_size = keys.size();
46 m_size = m_parallel_mng->reduce(Parallel::ReduceMax, m_init_size);
48 m_keys.resize(m_size);
49 m_key_ranks.resize(m_size);
50 m_key_indexes.resize(m_size);
52 Int32 rank = m_parallel_mng->commRank();
56 for (Integer i = 0; i < m_init_size; ++i) {
59 m_key_ranks[i] = rank;
64 KeyType max_value = KeyTypeTraits::maxValue();
65 for (Int64 i = m_init_size; i < m_size; i++) {
66 m_keys[i] = max_value;
67 m_key_indexes[i] = -1;
68 m_key_ranks[i] = rank;
85template <
typename KeyType,
typename KeyTypeTraits>
void
93 info() <<
"BITONIC_SORT (64bit) want_rank?=" << m_want_index_and_rank
95 <<
" memsize=" <<
sizeof(KeyType) * m_size
96 <<
" structsize=" <<
sizeof(KeyType);
104 Int32 nb_rank = m_parallel_mng->commSize();
105 while (nb_rank > test) {
112 for (Int32 ilevel = 0; ilevel < nb_level; ++ilevel) {
116 for (Int32 jproc = 0; jproc < nb_rank; jproc += size) {
117 _mergeLevels(jproc, size);
125 for (Integer i = 0; i < m_size; ++i) {
126 if (!KeyTypeTraits::isValid(m_keys[i])) {
132 info() <<
"END_BITONIC_SORT nb_merge=" << m_nb_merge;
134 m_keys.resize(m_size);
135 m_key_ranks.resize(m_size);
136 m_key_indexes.resize(m_size);
151template <
typename KeyType,
typename KeyTypeTraits>
void
156 for (Int32 i = 0; i < size / 2; ++i)
157 _mergeProcessors(begin + i, begin + size - 1 - i);
163 Int32 div_size = size;
164 while (div_size > 1) {
166 for (Int32 iproc = 0; iproc < size; iproc += div_size)
167 _separator(begin + iproc, div_size);
176template <
typename KeyType,
typename KeyTypeTraits>
void BitonicSort<KeyType, KeyTypeTraits>::
177_separator(Int32 begin, Int32 size)
179 for (Int32 i = 0; i < size / 2; ++i)
180 _mergeProcessors(begin + i, begin + i + size / 2);
199template <
typename KeyType,
typename KeyTypeTraits>
void BitonicSort<KeyType, KeyTypeTraits>::
200_mergeProcessors(Int32 iproc1, Int32 iproc2)
202 if (iproc1 >= iproc2)
203 ARCANE_FATAL(
"Invalid merge iproc1={0} iproc2={1}", iproc1, iproc2);
205 Int32 my_rank = m_parallel_mng->commRank();
207 if (iproc2 >= m_parallel_mng->commSize())
210 bool is_proc2 = (iproc2 == my_rank);
211 bool is_proc1 = (iproc1 == my_rank);
213 if (!is_proc1 && !is_proc2)
216 info() <<
"SORT iproc1=" << iproc1 <<
" iproc2=" << iproc2;
219 const Int64 buf_size = m_size;
220 const bool is_want_index_rank = m_want_index_and_rank;
227 UniqueArray<KeyType> send_keys(m_keys);
228 UniqueArray<Request> requests;
229 requests.add(KeyTypeTraits::send(m_parallel_mng, iproc1, send_keys));
230 if (is_want_index_rank) {
231 requests.add(m_parallel_mng->send(m_key_indexes, iproc1,
false));
232 requests.add(m_parallel_mng->send(m_key_ranks, iproc1,
false));
235 requests.add(KeyTypeTraits::recv(m_parallel_mng, iproc1, m_keys));
236 if (is_want_index_rank) {
237 requests.add(m_parallel_mng->recv(m_key_indexes, iproc1,
false));
238 requests.add(m_parallel_mng->recv(m_key_ranks, iproc1,
false));
240 m_parallel_mng->waitAllRequests(requests);
249 UniqueArray<KeyType> buf2(buf_size);
255 if (is_want_index_rank) {
256 buf2_proc.resize(buf_size);
257 buf2_local_id.resize(buf_size);
260 Request recv_request = KeyTypeTraits::recv(m_parallel_mng, iproc2, buf2);
261 m_parallel_mng->waitAllRequests(ArrayView<Request>(1, &recv_request));
262 if (is_want_index_rank) {
263 m_parallel_mng->recv(buf2_local_id, iproc2);
264 m_parallel_mng->recv(buf2_proc, iproc2);
268 buf2.add(KeyTypeTraits::maxValue());
271 Int64 total_size = m_size + buf_size;
272 UniqueArray<KeyType> buf_merge(total_size);
273 UniqueArray<Int32> buf_proc_merge;
274 UniqueArray<Int32> buf_local_id_merge;
275 if (is_want_index_rank) {
276 buf_proc_merge.resize(total_size);
277 buf_local_id_merge.resize(total_size);
281 info() <<
"SIZE=" << buf_size <<
" total=" << total_size <<
" m_size=" << m_size
282 <<
" proc2=" << iproc2 <<
" init-size=" << m_init_size;
289 for (Int64 i = 0; i < total_size; ++i) {
290 if (cursor1 >= m_size || (KeyTypeTraits::compareLess(buf2[cursor2], m_keys[cursor1]) && cursor2 < buf_size)) {
291 buf_merge[i] = buf2[cursor2];
292 if (is_want_index_rank) {
293 buf_local_id_merge[i] = buf2_local_id[cursor2];
294 buf_proc_merge[i] = buf2_proc[cursor2];
299 buf_merge[i] = m_keys[cursor1];
300 if (is_want_index_rank) {
301 buf_local_id_merge[i] = m_key_indexes[cursor1];
302 buf_proc_merge[i] = m_key_ranks[cursor1];
307 buf2.resize(buf_size);
310 for (Integer ii = 0; ii < buf_size; ii++) {
311 buf2[ii] = buf_merge[m_size + ii];
312 if (is_want_index_rank) {
313 buf2_local_id[ii] = buf_local_id_merge[m_size + ii];
314 buf2_proc[ii] = buf_proc_merge[m_size + ii];
317 Request send_request = KeyTypeTraits::send(m_parallel_mng, iproc2, buf2);
318 m_parallel_mng->waitAllRequests(ArrayView<Request>(1, &send_request));
319 if (is_want_index_rank) {
320 m_parallel_mng->send(buf2_local_id, iproc2);
321 m_parallel_mng->send(buf2_proc, iproc2);
325 for (Integer i = 0; i < buf_size; i++) {
326 m_keys[i] = buf_merge[i];
327 if (is_want_index_rank) {
328 m_key_indexes[i] = buf_local_id_merge[i];
329 m_key_ranks[i] = buf_proc_merge[i];
343template <
typename KeyType,
typename KeyTypeTraits>
void BitonicSort<KeyType, KeyTypeTraits>::
351 Int64 l = m_size / 2;
352 Int64 ir = m_size - 1;
356 Integer tmp_local_id = NULL_ITEM_LOCAL_ID;
357 Integer tmp_proc = A_NULL_RANK;
363 tmp_local_id = m_key_indexes[l];
364 tmp_proc = m_key_ranks[l];
368 tmp_local_id = m_key_indexes[ir];
369 tmp_proc = m_key_ranks[ir];
371 m_keys[ir] = m_keys[0];
372 m_key_indexes[ir] = m_key_indexes[0];
373 m_key_ranks[ir] = m_key_ranks[0];
377 m_key_indexes[0] = tmp_local_id;
378 m_key_ranks[0] = tmp_proc;
385 if (j < ir && KeyTypeTraits::compareLess(m_keys[j], m_keys[j + 1]))
387 if (KeyTypeTraits::compareLess(rra, m_keys[j])) {
388 m_keys[i] = m_keys[j];
389 m_key_indexes[i] = m_key_indexes[j];
390 m_key_ranks[i] = m_key_ranks[j];
399 m_key_indexes[i] = tmp_local_id;
400 m_key_ranks[i] = tmp_proc;
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Algorithme de tri bitonique parallèle.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
Vue constante d'un tableau de type T.
Implémentation de la concurrence.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Int32 Integer
Type représentant un entier.