Skip to content

Commit e66d6d1

Browse files
authored
Merge Add distributed L1 smoother
This PR adds a distributed version of #1310. It only uses the non-local matrix to create the additional diagonal matrix which is added to the local matrix. Related PR: #1806
2 parents 2acbcdd + a218c9d commit e66d6d1

File tree

10 files changed

+177
-21
lines changed

10 files changed

+177
-21
lines changed

common/unified/matrix/csr_kernels.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
1+
// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors
22
//
33
// SPDX-License-Identifier: BSD-3-Clause
44

@@ -313,6 +313,27 @@ void benchmark_lookup(std::shared_ptr<const DefaultExecutor> exec,
313313
GKO_INSTANTIATE_FOR_EACH_INDEX_TYPE(GKO_DECLARE_CSR_BENCHMARK_LOOKUP_KERNEL);
314314

315315

316+
template <typename ValueType, typename IndexType>
317+
void row_wise_absolute_sum(std::shared_ptr<const DefaultExecutor> exec,
318+
const matrix::Csr<ValueType, IndexType>* orig,
319+
array<ValueType>& sum)
320+
{
321+
run_kernel(
322+
exec,
323+
[] GKO_KERNEL(auto row, auto row_ptrs, auto value_ptr, auto sum_ptr) {
324+
sum_ptr[row] = zero<device_type<ValueType>>();
325+
for (auto k = row_ptrs[row]; k < row_ptrs[row + 1]; ++k) {
326+
sum_ptr[row] += abs(value_ptr[k]);
327+
}
328+
},
329+
sum.get_num_elems(), orig->get_const_row_ptrs(),
330+
orig->get_const_values(), sum.get_data());
331+
}
332+
333+
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(
334+
GKO_DECLARE_CSR_ROW_WISE_ABSOLUTE_SUM);
335+
336+
316337
} // namespace csr
317338
} // namespace GKO_DEVICE_NAMESPACE
318339
} // namespace kernels

core/device_hooks/common_kernels.inc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,7 @@ GKO_STUB_VALUE_AND_INDEX_TYPE(
767767
GKO_STUB_INDEX_TYPE(GKO_DECLARE_CSR_BUILD_LOOKUP_OFFSETS_KERNEL);
768768
GKO_STUB_INDEX_TYPE(GKO_DECLARE_CSR_BUILD_LOOKUP_KERNEL);
769769
GKO_STUB_INDEX_TYPE(GKO_DECLARE_CSR_BENCHMARK_LOOKUP_KERNEL);
770+
GKO_STUB_VALUE_AND_INDEX_TYPE(GKO_DECLARE_CSR_ROW_WISE_ABSOLUTE_SUM);
770771

771772
template <typename ValueType, typename IndexType>
772773
GKO_DECLARE_CSR_SCALE_KERNEL(ValueType, IndexType)

core/distributed/preconditioner/schwarz.cpp

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,26 @@
1717
#include <ginkgo/core/distributed/matrix.hpp>
1818
#include <ginkgo/core/matrix/csr.hpp>
1919
#include <ginkgo/core/matrix/dense.hpp>
20+
#include <ginkgo/core/matrix/identity.hpp>
2021

2122
#include "core/base/utils.hpp"
2223
#include "core/config/config_helper.hpp"
2324
#include "core/config/dispatch.hpp"
2425
#include "core/distributed/helpers.hpp"
26+
#include "core/matrix/csr_kernels.hpp"
2527

2628

2729
namespace gko {
2830
namespace experimental {
2931
namespace distributed {
3032
namespace preconditioner {
33+
namespace {
34+
35+
36+
GKO_REGISTER_OPERATION(row_wise_absolute_sum, csr::row_wise_absolute_sum);
37+
38+
39+
}
3140

3241

3342
template <typename ValueType, typename LocalIndexType, typename GlobalIndexType>
@@ -36,7 +45,7 @@ Schwarz<ValueType, LocalIndexType, GlobalIndexType>::parse(
3645
const config::pnode& config, const config::registry& context,
3746
const config::type_descriptor& td_for_child)
3847
{
39-
auto params = Schwarz<ValueType, LocalIndexType, GlobalIndexType>::build();
48+
auto params = Schwarz::build();
4049

4150
if (auto& obj = config.get("generated_local_solver")) {
4251
params.with_generated_local_solver(
@@ -47,7 +56,9 @@ Schwarz<ValueType, LocalIndexType, GlobalIndexType>::parse(
4756
gko::config::parse_or_get_factory<const LinOpFactory>(
4857
obj, context, td_for_child));
4958
}
50-
59+
if (auto& obj = config.get("l1_smoother")) {
60+
params.with_l1_smoother(obj.get_boolean());
61+
}
5162
return params;
5263
}
5364

@@ -76,7 +87,6 @@ template <typename VectorType>
7687
void Schwarz<ValueType, LocalIndexType, GlobalIndexType>::apply_dense_impl(
7788
const VectorType* dense_b, VectorType* dense_x) const
7889
{
79-
using Vector = matrix::Dense<ValueType>;
8090
auto exec = this->get_executor();
8191
if (this->local_solver_ != nullptr) {
8292
this->local_solver_->apply(gko::detail::get_local(dense_b),
@@ -130,14 +140,48 @@ void Schwarz<ValueType, LocalIndexType, GlobalIndexType>::generate(
130140
"Requires either a generated solver or an solver factory");
131141
}
132142

133-
if (parameters_.local_solver) {
134-
this->set_solver(gko::share(parameters_.local_solver->generate(
135-
as<experimental::distributed::Matrix<
136-
ValueType, LocalIndexType, GlobalIndexType>>(system_matrix)
137-
->get_local_matrix())));
143+
if (parameters_.generated_local_solver) {
144+
this->set_solver(parameters_.generated_local_solver);
145+
return;
146+
}
138147

148+
auto local_matrix =
149+
as<Matrix<ValueType, LocalIndexType, GlobalIndexType>>(system_matrix)
150+
->get_local_matrix();
151+
152+
if (parameters_.l1_smoother) {
153+
auto exec = this->get_executor();
154+
155+
using Csr = matrix::Csr<ValueType, LocalIndexType>;
156+
auto local_matrix_copy = share(Csr::create(exec));
157+
as<ConvertibleTo<Csr>>(local_matrix)->convert_to(local_matrix_copy);
158+
159+
auto non_local_matrix = copy_and_convert_to<Csr>(
160+
exec, as<Matrix<ValueType, LocalIndexType, GlobalIndexType>>(
161+
system_matrix)
162+
->get_non_local_matrix());
163+
164+
array<ValueType> l1_diag_arr{exec, local_matrix->get_size()[0]};
165+
166+
exec->run(
167+
make_row_wise_absolute_sum(non_local_matrix.get(), l1_diag_arr));
168+
169+
// compute local_matrix_copy <- diag(l1) + local_matrix_copy
170+
auto l1_diag = matrix::Diagonal<ValueType>::create(
171+
exec, local_matrix->get_size()[0], std::move(l1_diag_arr));
172+
auto l1_diag_csr = Csr::create(exec);
173+
l1_diag->move_to(l1_diag_csr);
174+
auto id = matrix::Identity<ValueType>::create(
175+
exec, local_matrix->get_size()[0]);
176+
auto one = initialize<matrix::Dense<ValueType>>(
177+
{::gko::one<ValueType>()}, exec);
178+
l1_diag_csr->apply(one, id, one, local_matrix_copy);
179+
180+
this->set_solver(
181+
gko::share(parameters_.local_solver->generate(local_matrix_copy)));
139182
} else {
140-
this->set_solver(parameters_.generated_local_solver);
183+
this->set_solver(
184+
gko::share(parameters_.local_solver->generate(local_matrix)));
141185
}
142186
}
143187

core/matrix/csr_kernels.hpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
1+
// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors
22
//
33
// SPDX-License-Identifier: BSD-3-Clause
44

@@ -258,6 +258,12 @@ namespace kernels {
258258
IndexType sample_size, IndexType* result)
259259

260260

261+
#define GKO_DECLARE_CSR_ROW_WISE_ABSOLUTE_SUM(ValueType, IndexType) \
262+
void row_wise_absolute_sum(std::shared_ptr<const DefaultExecutor> exec, \
263+
const matrix::Csr<ValueType, IndexType>* orig, \
264+
array<ValueType>& sum)
265+
266+
261267
#define GKO_DECLARE_ALL_AS_TEMPLATES \
262268
template <typename MatrixValueType, typename InputValueType, \
263269
typename OutputValueType, typename IndexType> \
@@ -336,7 +342,9 @@ namespace kernels {
336342
template <typename IndexType> \
337343
GKO_DECLARE_CSR_BUILD_LOOKUP_KERNEL(IndexType); \
338344
template <typename IndexType> \
339-
GKO_DECLARE_CSR_BENCHMARK_LOOKUP_KERNEL(IndexType)
345+
GKO_DECLARE_CSR_BENCHMARK_LOOKUP_KERNEL(IndexType); \
346+
template <typename ValueType, typename IndexType> \
347+
GKO_DECLARE_CSR_ROW_WISE_ABSOLUTE_SUM(ValueType, IndexType)
340348

341349

342350
GKO_DECLARE_FOR_ALL_EXECUTOR_NAMESPACES(csr, GKO_DECLARE_ALL_AS_TEMPLATES);

core/test/config/preconditioner.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ struct Schwarz
437437
config_map["generated_local_solver"] = pnode{"linop"};
438438
param.with_generated_local_solver(
439439
detail::registry_accessor::get_data<gko::LinOp>(reg, "linop"));
440+
config_map["l1_smoother"] = pnode{true};
441+
param.with_l1_smoother(true);
440442
}
441443

442444
template <bool from_reg, typename AnswerType>

include/ginkgo/core/distributed/preconditioner/schwarz.hpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
1+
// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors
22
//
33
// SPDX-License-Identifier: BSD-3-Clause
44

@@ -89,6 +89,16 @@ class Schwarz
8989
*/
9090
std::shared_ptr<const LinOp> GKO_FACTORY_PARAMETER_SCALAR(
9191
generated_local_solver, nullptr);
92+
93+
/**
94+
* Enable l1 smoother.
95+
*
96+
* This creates a diagonal matrix from the row-wise absolute
97+
* sum of the non-local matrix entries. The diagonal matrix
98+
* is then added to the system matrix when generating the
99+
* local solver.
100+
*/
101+
bool GKO_FACTORY_PARAMETER_SCALAR(l1_smoother, false);
92102
};
93103
GKO_ENABLE_LIN_OP_FACTORY(Schwarz, parameters, Factory);
94104
GKO_ENABLE_BUILD_METHOD(Factory);

reference/matrix/csr_kernels.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,6 +1458,28 @@ void benchmark_lookup(std::shared_ptr<const DefaultExecutor> exec,
14581458
GKO_INSTANTIATE_FOR_EACH_INDEX_TYPE(GKO_DECLARE_CSR_BENCHMARK_LOOKUP_KERNEL);
14591459

14601460

1461+
template <typename ValueType, typename IndexType>
1462+
void row_wise_absolute_sum(std::shared_ptr<const DefaultExecutor> exec,
1463+
const matrix::Csr<ValueType, IndexType>* orig,
1464+
array<ValueType>& sum)
1465+
{
1466+
auto row_ptrs = orig->get_const_row_ptrs();
1467+
auto value_ptr = orig->get_const_values();
1468+
auto sum_ptr = sum.get_data();
1469+
1470+
for (size_type row = 0; row < orig->get_size()[0]; ++row) {
1471+
sum_ptr[row] = zero<ValueType>();
1472+
for (size_type k = row_ptrs[row];
1473+
k < static_cast<size_type>(row_ptrs[row + 1]); ++k) {
1474+
sum_ptr[row] += abs(value_ptr[k]);
1475+
}
1476+
}
1477+
}
1478+
1479+
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(
1480+
GKO_DECLARE_CSR_ROW_WISE_ABSOLUTE_SUM);
1481+
1482+
14611483
} // namespace csr
14621484
} // namespace reference
14631485
} // namespace kernels

reference/test/matrix/csr_kernels.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2558,6 +2558,21 @@ TYPED_TEST(Csr, CanGetSubmatrixWithIndexSet)
25582558
}
25592559

25602560

2561+
TYPED_TEST(Csr, CanComputeRowWiseAbsoluteSum)
2562+
{
2563+
using value_type = typename TestFixture::value_type;
2564+
gko::array<value_type> sum(this->exec, this->mtx3_sorted->get_size()[0]);
2565+
this->create_mtx3(this->mtx3_sorted.get(), this->mtx3_unsorted.get());
2566+
this->mtx3_sorted->scale(gko::initialize<gko::matrix::Dense<value_type>>(
2567+
{-gko::one<value_type>()}, this->exec));
2568+
2569+
gko::kernels::reference::csr::row_wise_absolute_sum(
2570+
this->exec, this->mtx3_sorted.get(), sum);
2571+
2572+
gko::array<value_type> sum_result(this->exec, {3, 12, 5});
2573+
GKO_ASSERT_ARRAY_EQ(sum, sum_result);
2574+
}
2575+
25612576
template <typename ValueIndexType>
25622577
class CsrLookup : public ::testing::Test {
25632578
protected:

test/matrix/csr_kernels.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
1+
// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors
22
//
33
// SPDX-License-Identifier: BSD-3-Clause
44

@@ -78,6 +78,20 @@ TEST_F(Csr, InvScaleIsEquivalentToRef)
7878
}
7979

8080

81+
TEST_F(Csr, RowWiseSumIsEquivalentToRef)
82+
{
83+
set_up_apply_data();
84+
gko::array<value_type> sum{ref, x->get_size()[0]};
85+
gko::array<value_type> dsum{exec, dx->get_size()[0]};
86+
87+
gko::kernels::reference::csr::row_wise_absolute_sum(ref, x.get(), sum);
88+
gko::kernels::GKO_DEVICE_NAMESPACE::csr::row_wise_absolute_sum(
89+
exec, dx.get(), dsum);
90+
91+
GKO_ASSERT_ARRAY_EQ(sum, dsum);
92+
}
93+
94+
8195
template <typename IndexType>
8296
class CsrLookup : public CommonTestFixture {
8397
public:

test/mpi/preconditioner/schwarz.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,6 @@
3232
#include "test/utils/mpi/common_fixture.hpp"
3333

3434

35-
#if GINKGO_DPCPP_SINGLE_MODE
36-
using solver_value_type = float;
37-
#else
38-
using solver_value_type = double;
39-
#endif // GINKGO_DPCPP_SINGLE_MODE
40-
41-
4235
template <typename ValueLocalGlobalIndexType>
4336
class SchwarzPreconditioner : public CommonMpiTestFixture {
4437
protected:
@@ -296,3 +289,29 @@ TYPED_TEST(SchwarzPreconditioner, CanAdvancedApplyPreconditioner)
296289
this->assert_equal_to_non_distributed_vector(this->dist_x,
297290
this->non_dist_x);
298291
}
292+
293+
294+
TYPED_TEST(SchwarzPreconditioner, CanApplyPreconditionerWithL1Smoother)
295+
{
296+
using value_type = typename TestFixture::value_type;
297+
using prec = typename TestFixture::dist_prec_type;
298+
using local_matrix_type = typename TestFixture::local_matrix_type;
299+
auto non_dist_diag_with_l1 =
300+
gko::share(gko::matrix::Diagonal<value_type>::create(
301+
this->exec, 8u,
302+
gko::array<value_type>(this->exec, {2, 3, 3, 3, 3, 2, 2, 2})));
303+
auto precond_factory = prec::build()
304+
.with_local_solver(this->local_solver_factory)
305+
.with_l1_smoother(true)
306+
.on(this->exec);
307+
auto local_precond = this->local_solver_factory->generate(
308+
gko::copy_and_convert_to<local_matrix_type>(this->exec,
309+
non_dist_diag_with_l1));
310+
auto precond = precond_factory->generate(this->dist_mat);
311+
312+
precond->apply(this->dist_b.get(), this->dist_x.get());
313+
local_precond->apply(this->non_dist_b.get(), this->non_dist_x.get());
314+
315+
this->assert_equal_to_non_distributed_vector(this->dist_x,
316+
this->non_dist_x);
317+
}

0 commit comments

Comments
 (0)