Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DistributedSPMM.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/*---------------------------------------------------------------------------*/
9/*
10 * Ce fichier est basé sur le travail sur la bibliothèque AMGCL (version mars 2026)
11 * qui peut être trouvée à https://github.com/ddemidov/amgcl.
12 *
13 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
14 * SPDX-License-Identifier: MIT
15 */
16/*---------------------------------------------------------------------------*/
17/*---------------------------------------------------------------------------*/
18
19#include "arccore/alina/BuiltinBackend.h"
20#include "arccore/alina/StaticMatrix.h"
21#include "arccore/alina/Adapters.h"
22#include "arccore/alina/DistributedMatrix.h"
23#include "arccore/alina/IO.h"
24
25#include "arccore/alina/Profiler.h"
26
27#include <iostream>
28#include <vector>
29
30using namespace Arcane;
31
32namespace math = Alina::math;
33
34template <class Val>
35void assemble(int n, int beg, int end,
36 std::vector<int>& ptr,
37 std::vector<int>& col,
38 std::vector<Val>& val)
39{
40 int chunk = end - beg;
41
42 ptr.clear();
43 ptr.reserve(chunk + 1);
44 ptr.push_back(0);
45 col.clear();
46 col.reserve(chunk * 4);
47 val.clear();
48 val.reserve(chunk * 4);
49
50 for (int j = beg, i = 0; j < end; ++j, ++i) {
51 if (j > 0) {
52 col.push_back(j - 1);
53 val.push_back(-math::identity<Val>());
54 }
55
56 col.push_back(j);
57 val.push_back(2 * math::identity<Val>());
58
59 if (j + 1 < n) {
60 col.push_back(j + 1);
61 val.push_back(-math::identity<Val>());
62 }
63
64 if (j + 5 < n) {
65 col.push_back(j + 5);
66 val.push_back(-0.1 * math::identity<Val>());
67 }
68
69 ptr.push_back(col.size());
70 }
71}
72
73template <class Val>
74void test()
75{
76 // Dans le cas d'un bloc, Rhs peut être une StaticMatrix.
77 using Rhs = math::rhs_of<Val>::type;
78 using ScalarRhs = math::scalar_of<Rhs>::type;
79 int nb_scalar_for_rhs = sizeof(Rhs) / sizeof(ScalarRhs);
80
81 Alina::mpi_communicator comm(MPI_COMM_WORLD);
82 IMessagePassingMng* pm = comm.m_message_passing_mng.get();
83
84 int n = 16;
85 int chunk_len = (n + comm.size - 1) / comm.size;
86 int chunk_beg = std::min(n, chunk_len * comm.rank);
87 int chunk_end = std::min(n, chunk_len * (comm.rank + 1));
88 int chunk = chunk_end - chunk_beg;
89
90 UniqueArray<int> chunks(comm.size);
91 ConstArrayView<int> sent_chunk(1,&chunk);
92 mpAllGather(pm,sent_chunk,chunks);
93
94 std::vector<int> ptr;
95 std::vector<int> col;
96 std::vector<Val> val;
97 std::vector<Rhs> x(chunk);
98 std::vector<Rhs> y(chunk);
99
100 assemble(n, chunk_beg, chunk_end, ptr, col, val);
101
102 for (int i = 0; i < chunk; ++i)
103 x[i] = math::constant<Rhs>(drand48());
104
105 typedef Alina::BuiltinBackend<Val> Backend;
107
108 Matrix A(comm, std::tie(chunk, ptr, col, val), chunk);
109
110 auto B = Alina::product(A, A);
111 B->move_to_backend();
112
113 Alina::backend::spmv(1, *B, x, 0, y);
114
115 // Parce que Rhs peut être une StaticMatrix et n'est pas un type de base
116 // nous le convertissons en un tableau de type de base (qui est math::scalar_of<Rhs>::type).
119 Span<const ScalarRhs> scalar_x_view(reinterpret_cast<ScalarRhs*>(x.data()), x.size() * nb_scalar_for_rhs);
120 Span<const ScalarRhs> scalar_r_view(reinterpret_cast<ScalarRhs*>(y.data()), y.size() * nb_scalar_for_rhs);
121 mpGatherVariable(pm, scalar_x_view, scalarX, 0);
122 mpGatherVariable(pm, scalar_r_view, scalarR, 0);
123
124 if (comm.rank == 0) {
125 std::cout << "Doing verification size=" << scalarX.size() << "\n";
126 Rhs* scalar_x_begin = reinterpret_cast<Rhs*>(scalarX.data());
127 std::vector<Rhs> X(scalar_x_begin, scalar_x_begin + n);
128
129 Rhs* scalar_r_begin = reinterpret_cast<Rhs*>(scalarR.data());
130 std::vector<Rhs> R(scalar_r_begin, scalar_r_begin + n);
131
132 std::vector<Rhs> Y(n);
133 assemble(n, 0, n, ptr, col, val);
134
135 Alina::CSRMatrix<Val> A(std::tie(n, ptr, col, val));
136 Alina::backend::spmv(1, *product(A, A), X, 0, Y);
137
138 double s = 0;
139 for (int i = 0; i < n; ++i) {
140 double d = math::norm(R[i] - Y[i]);
141 s += d * d;
142 }
143 std::cout << "Error: " << s << std::endl;
144 }
145}
146
147int main(int argc, char* argv[])
148{
149 MPI_Init(&argc, &argv);
150
151 test<double>();
152 test<Alina::StaticMatrix<double, 2, 2>>();
153 MPI_Finalize();
154}
Integer size() const
Nombre d'éléments du vecteur.
Distributed Matrix using message passing.
const T * data() const
Accès à la racine du tableau hors toute protection.
Vue constante d'un tableau de type T.
Matrix class, to be used by user.
Interface du gestionnaire des échanges de messages.
Vue d'un tableau d'éléments de type T.
Definition Span.h:633
Vecteur 1D de données avec sémantique par valeur (style STL).
C void mpGatherVariable(IMessagePassingMng *pm, Span< const char > send_buf, Array< char > &recv_buf, Int32 rank)
void mpAllGather(IMessagePassingMng *pm, const ISerializer *send_serializer, ISerializer *receive_serialize)
Message allGather() pour une sérialisation.
Definition Messages.cc:308
Espace de nom pour les fonctions mathématiques.
Definition MathUtils.h:36
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Matrice creuse stockée au format CSR (Compressed Sparse Row).
Definition CSRMatrix.h:98
Wrapper de commodité autour de MPI_Comm.