Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
DistributedSPMMScaling.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 * This file is based on the work on AMGCL library (version march 2026)
11 * which can be found at 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 <iostream>
20#include <vector>
21
22#include "arccore/alina/BuiltinBackend.h"
23#include "arccore/alina/Adapters.h"
24#include "arccore/alina/DistributedMatrix.h"
25#include "arccore/alina/Profiler.h"
26
27#include "arccore/common/internal/ProgramOptions.h"
28
29#include "DomainPartition.h"
30
31using namespace Arcane;
32
33struct renumbering
34{
35 const DomainPartition<3>& part;
36 const UniqueArray<ptrdiff_t>& dom;
37
38 renumbering(const DomainPartition<3>& p,
39 const UniqueArray<ptrdiff_t>& d)
40 : part(p)
41 , dom(d)
42 {}
43
44 ptrdiff_t operator()(ptrdiff_t i, ptrdiff_t j, ptrdiff_t k) const
45 {
46 boost::array<ptrdiff_t, 3> p = { { i, j, k } };
47 std::pair<int, ptrdiff_t> v = part.index(p);
48 return dom[v.first] + v.second;
49 }
50};
51
52int main(int argc, char* argv[])
53{
54 auto& prof = Alina::Profiler::globalProfiler();
55
56 auto mpm = MessagePassing::Mpi::StandaloneMpiMessagePassingMng::createAndInitializeMPI(&argc, &argv, MPI_THREAD_MULTIPLE);
57 Alina::AlinaCommunicator world(mpm);
58
59 if (world.rank == 0)
60 std::cout << "World size: " << world.size << std::endl;
61
62 // Read configuration from command line
63 ptrdiff_t n = 128;
64
65 namespace po = Arcane::ProgramOptions;
66 po::options_description desc("Options");
67
68 desc.add_options()("help,h", "show help")(
69 "size,n",
70 po::value<ptrdiff_t>(&n)->default_value(n),
71 "domain size");
72
74 po::store(po::parse_command_line(argc, argv, desc), vm);
75 po::notify(vm);
76
77 if (vm.count("help")) {
78 std::cout << desc << std::endl;
79 return 0;
80 }
81
82 boost::array<ptrdiff_t, 3> lo = { { 0, 0, 0 } };
83 boost::array<ptrdiff_t, 3> hi = { { n - 1, n - 1, n - 1 } };
84
85 prof.tic("partition");
86 DomainPartition<3> part(lo, hi, world.size);
87 ptrdiff_t chunk = part.size(world.rank);
88
89 UniqueArray<ptrdiff_t> domain = world.exclusive_sum(chunk);
90
91 lo = part.domain(world.rank).min_corner();
92 hi = part.domain(world.rank).max_corner();
93
94 renumbering renum(part, domain);
95 prof.toc("partition");
96
97 prof.tic("assemble");
98 std::vector<ptrdiff_t> ptr;
99 std::vector<ptrdiff_t> col;
100 std::vector<double> val;
101 std::vector<double> rhs;
102
103 ptr.reserve(chunk + 1);
104 col.reserve(chunk * 7);
105 val.reserve(chunk * 7);
106
107 ptr.push_back(0);
108
109 const double h2i = (n - 1) * (n - 1);
110
111 for (ptrdiff_t k = lo[2]; k <= hi[2]; ++k) {
112 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
113 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
114 if (k > 0) {
115 col.push_back(renum(i, j, k - 1));
116 val.push_back(-h2i);
117 }
118
119 if (j > 0) {
120 col.push_back(renum(i, j - 1, k));
121 val.push_back(-h2i);
122 }
123
124 if (i > 0) {
125 col.push_back(renum(i - 1, j, k));
126 val.push_back(-h2i);
127 }
128
129 col.push_back(renum(i, j, k));
130 val.push_back(6 * h2i);
131
132 if (i + 1 < n) {
133 col.push_back(renum(i + 1, j, k));
134 val.push_back(-h2i);
135 }
136
137 if (j + 1 < n) {
138 col.push_back(renum(i, j + 1, k));
139 val.push_back(-h2i);
140 }
141
142 if (k + 1 < n) {
143 col.push_back(renum(i, j, k + 1));
144 val.push_back(-h2i);
145 }
146
147 ptr.push_back(col.size());
148 }
149 }
150 }
151 prof.toc("assemble");
152
153 typedef Alina::BuiltinBackend<double> Backend;
155
156 prof.tic("create distributed version");
157 Matrix A(world, std::tie(chunk, ptr, col, val), chunk);
158 prof.toc("create distributed version");
159
160 prof.tic("distributed product");
161 auto B = product(A, A);
162 prof.toc("distributed product");
163
164 if (world.rank == 0) {
165 if (world.size == 1) {
166 typedef Alina::CSRMatrix<double> matrix;
167 matrix A(std::tie(chunk, ptr, col, val));
168 prof.tic("openmp product");
169 auto B = product(A, A);
170 prof.toc("openmp product");
171 }
172
173 std::cout << prof << std::endl;
174 }
175}
Distributed Matrix using message passing.
Matrix class, to be used by user.
static Ref< IMessagePassingMng > createAndInitializeMPI(int *argc, char **argv[], int wanted_thread_level)
Initialize MPI and creates a manager associated with the MPI_WORLD_COMM communicator.
Describes a set of command-line options.
Stores parsed option values.
1D data vector with value semantics (STL style).
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Convenience wrapper around MPI_Comm.
Sparse matrix stored in CSR (Compressed Sparse Row) format.
Definition CSRMatrix.h:98