Alien  1.3.0
Developer documentation
Loading...
Searching...
No Matches
sycl/data/DistStructInfo.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*
8 * Copyright 2020 IFPEN-CEA
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 * SPDX-License-Identifier: Apache-2.0
23 */
24
25/*
26 * DistStructInfo.cc
27 *
28 * Created on: Oct 1, 2010
29 * Author: gratienj
30 */
31
32#include "DistStructInfo.h"
33
34#include <map>
35#include <set>
36#include <sstream>
37
40
41#include "BEllPacktructInfo.h"
42#include "SendRecvOp.h"
43
44using namespace Arccore;
45using namespace Arccore::MessagePassing;
46
47namespace Alien::SimpleCSRInternal
48{
49void DistStructInfo::compute(Integer nproc, ConstArrayView<Integer> offset, Integer my_rank,
50 IMessagePassingMng* parallel_mng, const BaseBEllPackStructInfo& profile,
51 ITraceMng* trace ALIEN_UNUSED_PARAM)
52{
53#ifdef DEBUG
54 std::stringstream file("dd");
55 file << my_rank;
56 ofstream fout(file.str().c_str());
57#endif
58 std::vector<Integer> count(nproc);
59 count.assign(nproc, 0);
60 const Integer nrow = profile.getNRow();
61 ConstArrayView<Integer> row_offset = profile.getRowOffset();
62 // ArrayView<Integer> cols = profile->getCols();
63 m_cols.copy(profile.getCols());
64
65 Integer local_offset = offset[my_rank];
66
67 std::vector<std::map<Integer, Integer>> lids(nproc);
68 std::vector<std::set<Integer>> gids(nproc);
69 m_local_row_size.resize(nrow);
70 for (Integer irow = 0; irow < nrow; ++irow) {
71 Integer lrow_size = 0;
72 for (Integer icol = row_offset[irow]; icol < row_offset[irow + 1]; ++icol) {
73 Integer col_uid = m_cols[icol];
74 Integer ip = domainId(nproc, offset, col_uid);
75 // TODO: deal with ip == -1
76 // fout<<"col("<<col_uid<<","<<ip<<");";
77 if (ip == my_rank) {
78 // turn col global id to local id
79 m_cols[icol] = col_uid - local_offset;
80 ++lrow_size;
81 }
82 else {
83 /*
84 std::map<Integer, Integer>::iterator iter = lids[ip].find(col_uid);
85 if (iter == lids[ip].end()) {
86 // compute local id of ghost id
87 Integer col_lid = count[ip];
88 lids[ip].insert(std::pair<Integer, Integer>(col_uid, col_lid));
89 // cols[icol] = col_lid;
90 ++count[ip];
91 }*/
92 gids[ip].insert(col_uid);
93 }
94 }
95 // fout<<endl;
96 m_local_row_size[irow] = lrow_size;
97 if (lrow_size < row_offset[irow + 1] - row_offset[irow])
98 ++m_interface_nrow;
99 }
100 // COMPUTE GHOST LOCAL ID PER NEIGH DOMAIN
101 for (Integer ip = 0; ip < nproc; ++ip) {
102 Integer lid = 0;
103 auto& lids_ip = lids[ip];
104 for (Integer uid : gids[ip]) {
105 lids_ip.insert(std::make_pair(uid, lid));
106 ++lid;
107 }
108 }
109 {
110 m_interface_rows.resize(m_interface_nrow);
111 std::vector<Integer> col_offset(nproc + 1);
112 col_offset[0] = nrow;
113 for (Integer ip = 1; ip < nproc + 1; ++ip) {
114 // col_offset[ip] = col_offset[ip - 1] + count[ip - 1];
115 col_offset[ip] = col_offset[ip - 1] + gids[ip - 1].size();
116 }
117 std::size_t ghost_size = col_offset[nproc] - col_offset[0];
118 m_recv_info.m_rank_ids.resize(ghost_size);
119 m_recv_info.m_ids.resize(ghost_size);
120 Integer icount = 0;
121 Integer ghost_icount = 0;
122 std::set<Integer> ghost_set;
123 for (Integer irow = 0; irow < nrow; ++irow) {
124 if (m_local_row_size[irow] < row_offset[irow + 1] - row_offset[irow]) {
125 m_interface_rows[icount] = irow;
126 m_interface_row_set.insert(irow);
127 ++icount;
128 for (Integer icol = row_offset[irow] + m_local_row_size[irow];
129 icol < row_offset[irow + 1]; ++icol) {
130 // compute local id of ghost col id
131 Integer col_uid = m_cols[icol];
132 Integer ip = domainId(nproc, offset, col_uid);
133 m_cols[icol] = lids[ip][col_uid] + col_offset[ip];
134 auto const& iter = ghost_set.insert(col_uid);
135 if (iter.second) {
136 m_recv_info.m_rank_ids[ghost_icount] = ip;
137 m_recv_info.m_ids[ghost_icount] = m_cols[icol];
138 ++ghost_icount;
139 }
140 }
141 }
142 }
143 }
145 //
146 // compute mailing list for mat mult communication operation
147 //
148 // INFO to recv from neighbour processors
149 //
150 Integer nb_neighbour = 0;
151 Integer first_upper_neighb = 0;
152 for (Integer ip = 0; ip < nproc; ++ip)
153 // if (count[ip] > 0)
154 // ++nb_neighbour;
155 if (gids[ip].size() > 0) {
156 ++nb_neighbour;
157 if (ip < my_rank)
158 ++first_upper_neighb;
159 }
160
161 m_recv_info.m_num_neighbours = nb_neighbour;
162 m_recv_info.m_first_upper_neighb = first_upper_neighb;
163 m_recv_info.m_ranks.resize(nb_neighbour);
164 m_recv_info.m_ids_offset.resize(nb_neighbour + 1);
165 nb_neighbour = 0;
166 m_recv_info.m_ids_offset[0] = nrow;
167 for (Integer ip = 0; ip < nproc; ++ip)
168 // if (count[ip] > 0) {
169 if (gids[ip].size() > 0) {
170 m_recv_info.m_ranks[nb_neighbour] = ip;
171 // m_recv_info.m_ids_offset[nb_neighbour + 1] =
172 // m_recv_info.m_ids_offset[nb_neighbour] + count[ip];
173 m_recv_info.m_ids_offset[nb_neighbour + 1] =
174 m_recv_info.m_ids_offset[nb_neighbour] + gids[ip].size();
175 ++nb_neighbour;
176 }
177 m_ghost_nrow = m_recv_info.m_ids_offset[nb_neighbour] - nrow;
178 m_recv_info.m_uids.resize(m_ghost_nrow);
179 m_first_upper_ghost_index = m_recv_info.m_ids_offset[first_upper_neighb];
180 // m_recv_info->printInfo(trace->info().file());
181
183 //
184 // compute mailing list for mat mult communication operation
185 //
186 // INFO to send to neighbour processor
187 std::vector<std::vector<Integer>> send_ids(nproc);
188 nb_neighbour = 0;
189 Integer send_count = 0;
190 std::vector<Integer> buffer;
191 for (Integer ip = 0; ip < nproc; ++ip) {
192 if (ip == my_rank) {
193 Integer offset = 0;
194 for (Integer ip2 = 0; ip2 < nproc; ++ip2) {
195 if (ip2 != my_rank) {
196 // Integer nids = lids[ip2].size();
197 // Integer nids = count[ip2];
198 Integer nids = gids[ip2].size();
199 // trace->info()<<"SEND to "<<ip2<<" nids="<<nids;
200 Arccore::MessagePassing::mpSend(
201 parallel_mng, ConstArrayView<Integer>(1, &nids), ip2);
202 if (nids > 0) {
203 buffer.clear();
204 buffer.resize(nids);
205 // buffer.reserve(nids);
206 std::map<Integer, Integer>::iterator iter = lids[ip2].begin();
207 while (iter != lids[ip2].end()) {
208 // buffer.push_back((*iter).first);
209 buffer[(*iter).second] = (*iter).first;
210 m_recv_info.m_uids[offset + (*iter).second] = (*iter).first;
211 ++iter;
212 }
213
214 Arccore::MessagePassing::mpSend(
215 parallel_mng, ConstArrayView<Integer>(nids, &buffer[0]), ip2);
216 offset += nids;
217 }
218 }
219 }
220 }
221 else {
222 Integer nids = 0;
223 Arccore::MessagePassing::mpReceive(parallel_mng, ArrayView<Integer>(1, &nids), ip);
224 // trace->info()<<"RECV from "<<ip<<" nids="<<nids;
225 if (nids > 0) {
226 ++nb_neighbour;
227 send_count += nids;
228 send_ids[ip].resize(nids);
229 Arccore::MessagePassing::mpReceive(
230 parallel_mng, ArrayView<Integer>(nids, &send_ids[ip][0]), ip);
231 }
232 }
233 }
234 m_send_info.m_num_neighbours = nb_neighbour;
235 m_send_info.m_ranks.resize(nb_neighbour);
236 m_send_info.m_ids.resize(send_count);
237 m_send_info.m_ids_offset.resize(nb_neighbour + 1);
238 first_upper_neighb = 0;
239 Integer icount = 0;
240 nb_neighbour = 0;
241 for (Integer ip = 0; ip < nproc; ++ip) {
242 if (send_ids[ip].size() > 0) {
243 m_send_info.m_ranks[nb_neighbour] = ip;
244 m_send_info.m_ids_offset[nb_neighbour] = icount;
245 ++nb_neighbour;
246 if (ip < my_rank)
247 ++first_upper_neighb;
248 std::size_t nids = send_ids[ip].size();
249 Integer* ids = &send_ids[ip][0];
250 for (auto i = 0; i < nids; ++i) {
251 m_send_info.m_ids[icount] = ids[i] - local_offset;
252 // fout<<"SEND : "<<ids[i]<<" "<<ids[i] - local_offset<<endl;
253 ++icount;
254 }
255 }
256 }
257 m_send_info.m_ids_offset[nb_neighbour] = icount;
258 m_send_info.m_first_upper_neighb = first_upper_neighb;
259
260 // m_send_info->printInfo(trace->info().file());
261}
262
263void DistStructInfo::compute(Integer nproc, ConstArrayView<Integer> offset, Integer my_rank,
264 IMessagePassingMng* parallel_mng, const BaseBEllPackStructInfo& profile,
265 const VBlock* block_sizes, const MatrixDistribution& dist,
266 ITraceMng* trace ALIEN_UNUSED_PARAM)
267{
268 // alien_info([&] {cout() << "DistStructInfo::compute VBlock";}) ;
269 std::vector<Integer> count(nproc);
270 count.assign(nproc, 0);
271 std::vector<Integer> block_count(nproc);
272 block_count.assign(nproc, 0);
273
274 Integer nrow = profile.getNRow();
275 ConstArrayView<Integer> row_offset = profile.getRowOffset();
276 m_cols.copy(profile.getCols());
277
278 VBlockImpl blocks(*block_sizes, dist);
279
280 Integer block_nrow = 0;
281 for (Integer i = 0; i < nrow; ++i) {
282 block_nrow += blocks.sizeFromLocalIndex(i);
283 }
284
285 Integer local_offset = offset[my_rank];
286
287 std::vector<std::map<Integer, Integer>> lids(nproc);
288 std::vector<std::set<Integer>> gids(nproc);
289 m_local_row_size.resize(nrow);
290 for (Integer irow = 0; irow < nrow; ++irow) {
291 Integer lrow_size = 0;
292 // fout<<"ROW("<<irow<<")";
293 for (Integer icol = row_offset[irow]; icol < row_offset[irow + 1]; ++icol) {
294 Integer col_uid = m_cols[icol];
295 Integer ip = domainId(nproc, offset, col_uid);
296 // TODO: Deal with ip == -1
297 // fout<<"col("<<col_uid<<","<<ip<<");";
298 if (ip == my_rank) {
299 // turn col global id to local id
300 m_cols[icol] = col_uid - local_offset;
301 ++lrow_size;
302 }
303 else {
304 /*
305 std::map<Integer, Integer>::iterator iter = lids[ip].find(col_uid);
306 if (iter == lids[ip].end()) {
307 // compute local id of ghost id
308 Integer col_lid = count[ip];
309 lids[ip].insert(std::pair<Integer, Integer>(col_uid, col_lid));
310 // cols[icol] = col_lid;
311 ++count[ip];
312 block_count[ip] += block_sizes->size(col_uid);
313 }*/
314 auto value = gids[ip].insert(col_uid);
315 if (value.second)
316 block_count[ip] += block_sizes->size(col_uid);
317 }
318 }
319 // fout<<endl;
320 m_local_row_size[irow] = lrow_size;
321 if (lrow_size < row_offset[irow + 1] - row_offset[irow])
322 ++m_interface_nrow;
323 }
324
325 // COMPUTE GHOST LOCAL ID PER NEIGH DOMAIN
326 for (int ip = 0; ip < nproc; ++ip) {
327 int lid = 0;
328 auto& lids_ip = lids[ip];
329 for (int uid : gids[ip]) {
330 lids_ip.insert(std::make_pair(uid, lid));
331 ++lid;
332 }
333 }
334
335 {
336 // Il faut une map ordonn?e
337 std::map<Integer, Integer> ghost_sizes;
338
339 // Integer icount = 0;
340 m_interface_rows.resize(m_interface_nrow);
341 std::vector<Integer> col_offset(nproc + 1);
342 col_offset[0] = nrow;
343 for (Integer ip = 1; ip < nproc + 1; ++ip)
344 // col_offset[ip] = col_offset[ip - 1] + count[ip - 1];
345 col_offset[ip] = col_offset[ip - 1] + gids[ip - 1].size();
346 std::size_t ghostsize = col_offset[nproc] - col_offset[0];
347 m_recv_info.m_rank_ids.resize(ghostsize);
348 m_recv_info.m_ids.resize(ghostsize);
349 int icount = 0;
350 int ghost_icount = 0;
351 std::set<int> ghost_set;
352 for (Integer irow = 0; irow < nrow; ++irow) {
353 if (m_local_row_size[irow] < row_offset[irow + 1] - row_offset[irow]) {
354 m_interface_rows[icount] = irow;
355 m_interface_row_set.insert(irow);
356 ++icount;
357 // fout<<my_rank<<" Interface row : "<<irow << std::endl;
358 for (Integer icol = row_offset[irow] + m_local_row_size[irow];
359 icol < row_offset[irow + 1]; ++icol) {
360 // compute local id of ghost col id
361 Integer col_uid = m_cols[icol];
362 Integer ip = domainId(nproc, offset, col_uid);
363 m_cols[icol] = lids[ip][col_uid] + col_offset[ip];
364 auto const& iter = ghost_set.insert(col_uid);
365 if (iter.second) {
366 m_recv_info.m_rank_ids[ghost_icount] = ip;
367 m_recv_info.m_ids[ghost_icount] = m_cols[icol];
368 ++ghost_icount;
369 }
370 // fout<<"COL["<<icol<<","<<col_uid<<"]="<<m_cols[icol]<<"
371 // "<<col_offset[ip]<<endl; trace->info()
372 // <<"COL["<<icol<<","<<col_uid<<"]="<<m_cols[icol]<<" "<<col_offset[ip];
373 ghost_sizes[m_cols[icol]] = block_sizes->size(col_uid);
374 // block_sizes.setGhostLocalId(col_uid,m_cols[icol]);
375 }
376 }
377 }
378
379 ConstArrayView<Integer> local_sizes = blocks.sizeOfLocalIndex();
380 ConstArrayView<Integer> local_offsets = blocks.offsetOfLocalIndex();
381
382 ALIEN_ASSERT(
383 (local_offsets.size() == local_sizes.size() + 1), ("sizes are different"));
384
385 const Integer size = local_sizes.size();
386 const Integer ghost_size = ghost_sizes.size();
387
388 m_block_sizes.resize(size + ghost_size);
389 m_block_offsets.resize(size + ghost_size);
390
391 for (Integer i = 0; i < size; ++i) {
392 m_block_sizes[i] = local_sizes[i];
393 m_block_offsets[i] = local_offsets[i];
394 }
395
396 for (std::map<Integer, Integer>::const_iterator it = ghost_sizes.begin();
397 it != ghost_sizes.end(); ++it) {
398 const Integer lid = it->first;
399 m_block_sizes[lid] = it->second;
400 m_block_offsets[lid] = m_block_offsets[lid - 1] + m_block_sizes[lid - 1];
401 }
402 }
403
404 // for(Integer i = 0; i < m_block_sizes.size(); ++i) {
405 // trace->info() << "block_sizes[" << i << "] = " << m_block_sizes[i];
406 // trace->info() << "block_offsets[" << i << "] = " << m_block_offsets[i];
407 // }
408
410 //
411 // compute mailing list for mat mult communication operation
412 //
413 // INFO to recv from neighbour processors
414 //
415 Integer nb_neighbour = 0;
416 // for (Integer ip = 0; ip < nproc; ++ip)
417 // if (count[ip] > 0)
418 // ++nb_neighbour;
419 int first_upper_neighb = 0;
420 for (int ip = 0; ip < nproc; ++ip)
421 if (gids[ip].size() > 0) {
422 ++nb_neighbour;
423 if (ip < my_rank)
424 ++first_upper_neighb;
425 }
426 m_recv_info.m_num_neighbours = nb_neighbour;
427 m_recv_info.m_first_upper_neighb = first_upper_neighb;
428 m_recv_info.m_ranks.resize(nb_neighbour);
429 m_recv_info.m_ids_offset.resize(nb_neighbour + 1);
430 m_recv_info.m_block_ids_offset.resize(nb_neighbour + 1);
431 nb_neighbour = 0;
432 m_recv_info.m_ids_offset[0] = nrow;
433 m_recv_info.m_block_ids_offset[0] = block_nrow;
434 for (Integer ip = 0; ip < nproc; ++ip)
435 // if (count[ip] > 0) {
436 if (gids[ip].size() > 0) {
437 m_recv_info.m_ranks[nb_neighbour] = ip;
438 // m_recv_info.m_ids_offset[nb_neighbour + 1] =
439 // m_recv_info.m_ids_offset[nb_neighbour] + count[ip];
440 m_recv_info.m_ids_offset[nb_neighbour + 1] =
441 m_recv_info.m_ids_offset[nb_neighbour] + gids[ip].size();
442 m_recv_info.m_block_ids_offset[nb_neighbour + 1] =
443 m_recv_info.m_block_ids_offset[nb_neighbour] + block_count[ip];
444 ++nb_neighbour;
445 }
446 m_ghost_nrow = m_recv_info.m_ids_offset[nb_neighbour] - nrow;
447 m_recv_info.m_uids.resize(m_ghost_nrow);
448 m_first_upper_ghost_index = m_recv_info.m_ids_offset[first_upper_neighb];
449
450 // m_recv_info.printInfo(recv_fout);
451
453 //
454 // compute mailing list for mat mult communication operation
455 //
456 // INFO to send to neighbour processor
457 std::vector<std::vector<Integer>> send_ids(nproc);
458 nb_neighbour = 0;
459 Integer send_count = 0;
460 std::vector<Integer> buffer;
461 for (Integer ip = 0; ip < nproc; ++ip) {
462 if (ip == my_rank) {
463 Integer offset = 0;
464 for (Integer ip2 = 0; ip2 < nproc; ++ip2) {
465 if (ip2 != my_rank) {
466 // Integer nids = lids[ip2].size();
467 // Integer nids = count[ip2];
468 Integer nids = gids[ip2].size();
469 // trace->info()<<"SEND to "<<ip2<<" nids="<<nids;
470 Arccore::MessagePassing::mpSend(
471 parallel_mng, ConstArrayView<Integer>(1, &nids), ip2);
472 if (nids > 0) {
473 buffer.clear();
474 buffer.resize(nids);
475 // buffer.reserve(nids);
476 std::map<Integer, Integer>::iterator iter = lids[ip2].begin();
477 while (iter != lids[ip2].end()) {
478 // buffer.push_back((*iter).first);
479 buffer[(*iter).second] = (*iter).first;
480 m_recv_info.m_uids[offset + (*iter).second] = (*iter).first;
481 ++iter;
482 }
483
484 Arccore::MessagePassing::mpSend(
485 parallel_mng, ConstArrayView<Integer>(nids, &buffer[0]), ip2);
486 offset += nids;
487 }
488 }
489 }
490 }
491 else {
492 Integer nids = 0;
493 Arccore::MessagePassing::mpReceive(parallel_mng, ArrayView<Integer>(1, &nids), ip);
494 // trace->info()<<"RECV from "<<ip<<" nids="<<nids;
495 if (nids > 0) {
496 ++nb_neighbour;
497 send_count += nids;
498 send_ids[ip].resize(nids);
499 Arccore::MessagePassing::mpReceive(
500 parallel_mng, ArrayView<Integer>(nids, &send_ids[ip][0]), ip);
501 }
502 }
503 }
504 m_send_info.m_num_neighbours = nb_neighbour;
505 m_send_info.m_ranks.resize(nb_neighbour);
506 m_send_info.m_ids.resize(send_count);
507 m_send_info.m_ids_offset.resize(nb_neighbour + 1);
508 m_send_info.m_block_ids_offset.resize(nb_neighbour + 1);
509 Integer icount = 0, block_icount = 0;
510 nb_neighbour = 0;
511 for (Integer ip = 0; ip < nproc; ++ip) {
512 if (send_ids[ip].size() > 0) {
513 m_send_info.m_ranks[nb_neighbour] = ip;
514 m_send_info.m_ids_offset[nb_neighbour] = icount;
515 m_send_info.m_block_ids_offset[nb_neighbour] = block_icount;
516 ++nb_neighbour;
517 if (ip < my_rank)
518 ++first_upper_neighb;
519 Integer nids = send_ids[ip].size();
520 Integer* ids = &send_ids[ip][0];
521 for (Integer i = 0; i < nids; ++i) {
522 m_send_info.m_ids[icount] = ids[i] - local_offset;
523 ++icount;
524 block_icount += m_block_sizes[ids[i] - local_offset];
525 }
526 }
527 }
528 m_send_info.m_ids_offset[nb_neighbour] = icount;
529 m_send_info.m_block_ids_offset[nb_neighbour] = block_icount;
530
531 // m_send_info.printInfo(send_fout);
532}
533
534void DistStructInfo::copy(const DistStructInfo& src)
535{
536 m_local_row_size.copy(src.m_local_row_size);
537 m_ghost_nrow = src.m_ghost_nrow;
538 m_interface_nrow = src.m_interface_nrow;
539
540 m_interface_rows.copy(src.m_interface_rows);
541 m_interface_row_set = src.m_interface_row_set;
542 m_cols.copy(src.m_cols);
543
544 m_block_sizes.copy(src.m_block_sizes);
545 m_block_offsets.copy(src.m_block_offsets);
546
547 m_recv_info.copy(src.m_recv_info);
548 m_send_info.copy(src.m_send_info);
549}
550
551} // namespace Alien::SimpleCSRInternal
VBlockOffsets.h.
VBlock.h.