From fef8ff372ef2c0dbe4b140a967d7421efb529ce1 Mon Sep 17 00:00:00 2001 From: "Yu-Hsiang M. Tsai" Date: Thu, 11 Jul 2024 00:12:01 +0200 Subject: [PATCH] add the infinite_norm --- .../matrix/dense_kernels.instantiate.cpp | 3 ++ .../unified/matrix/dense_kernels.template.cpp | 13 ++++++++ core/device_hooks/common_kernels.inc.cpp | 1 + core/matrix/dense.cpp | 30 +++++++++++++++++++ core/matrix/dense_kernels.hpp | 8 +++++ core/solver/ir.cpp | 2 +- include/ginkgo/core/matrix/dense.hpp | 21 +++++++++++++ reference/matrix/dense_kernels.cpp | 20 +++++++++++++ 8 files changed, 97 insertions(+), 1 deletion(-) diff --git a/common/unified/matrix/dense_kernels.instantiate.cpp b/common/unified/matrix/dense_kernels.instantiate.cpp index aca8ad5bec4..8dac6331c20 100644 --- a/common/unified/matrix/dense_kernels.instantiate.cpp +++ b/common/unified/matrix/dense_kernels.instantiate.cpp @@ -78,6 +78,9 @@ GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_NORM2_KERNEL); // split GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_NORM1_KERNEL); // split +GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE( + GKO_DECLARE_DENSE_COMPUTE_INFINITE_NORM_KERNEL); +// split GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE( GKO_DECLARE_DENSE_COMPUTE_MAX_NNZ_PER_ROW_KERNEL); // split diff --git a/common/unified/matrix/dense_kernels.template.cpp b/common/unified/matrix/dense_kernels.template.cpp index f5b3cc03059..8f2233242dd 100644 --- a/common/unified/matrix/dense_kernels.template.cpp +++ b/common/unified/matrix/dense_kernels.template.cpp @@ -249,6 +249,19 @@ void compute_norm1(std::shared_ptr exec, } +template +void compute_infinite_norm(std::shared_ptr exec, + const matrix::Dense* x, + matrix::Dense>* result, + array& tmp) +{ + run_kernel_col_reduction_cached( + exec, [] GKO_KERNEL(auto i, auto j, auto x) { return abs(x(i, j)); }, + GKO_KERNEL_REDUCE_MAX(remove_complex), result->get_values(), + x->get_size(), tmp, x); +} + + template void compute_mean(std::shared_ptr exec, const matrix::Dense* x, diff --git a/core/device_hooks/common_kernels.inc.cpp b/core/device_hooks/common_kernels.inc.cpp index de8a1ac0c56..c02d51647ff 100644 --- a/core/device_hooks/common_kernels.inc.cpp +++ b/core/device_hooks/common_kernels.inc.cpp @@ -351,6 +351,7 @@ GKO_STUB_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_CONJ_DOT_KERNEL); GKO_STUB_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_CONJ_DOT_DISPATCH_KERNEL); GKO_STUB_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_NORM2_KERNEL); GKO_STUB_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_NORM2_DISPATCH_KERNEL); +GKO_STUB_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_INFINITE_NORM_KERNEL); GKO_STUB_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_NORM1_KERNEL); GKO_STUB_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_MEAN_KERNEL); GKO_STUB_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_SQUARED_NORM2_KERNEL); diff --git a/core/matrix/dense.cpp b/core/matrix/dense.cpp index c9872a94b05..22f6be02238 100644 --- a/core/matrix/dense.cpp +++ b/core/matrix/dense.cpp @@ -53,6 +53,7 @@ GKO_REGISTER_OPERATION(sub_scaled_diag, dense::sub_scaled_diag); GKO_REGISTER_OPERATION(compute_dot, dense::compute_dot_dispatch); GKO_REGISTER_OPERATION(compute_conj_dot, dense::compute_conj_dot_dispatch); GKO_REGISTER_OPERATION(compute_norm2, dense::compute_norm2_dispatch); +GKO_REGISTER_OPERATION(compute_infinite_norm, dense::compute_infinite_norm); GKO_REGISTER_OPERATION(compute_norm1, dense::compute_norm1); GKO_REGISTER_OPERATION(compute_mean, dense::compute_mean); GKO_REGISTER_OPERATION(compute_squared_norm2, dense::compute_squared_norm2); @@ -204,6 +205,18 @@ void Dense::compute_norm2(ptr_param result) const } +template +void Dense::compute_infinite_norm(ptr_param result) const +{ + GKO_ASSERT_EQUAL_DIMENSIONS(result, dim<2>(1, this->get_size()[1])); + auto exec = this->get_executor(); + auto dense_res = + make_temporary_conversion>(result); + array tmp{exec}; + exec->run(dense::make_compute_infinite_norm(this, dense_res.get(), tmp)); +} + + template void Dense::compute_norm1(ptr_param result) const { @@ -424,6 +437,23 @@ void Dense::compute_norm2(ptr_param result, } +template +void Dense::compute_infinite_norm(ptr_param result, + array& tmp) const +{ + GKO_ASSERT_EQUAL_DIMENSIONS(result, dim<2>(1, this->get_size()[1])); + auto exec = this->get_executor(); + if (tmp.get_executor() != exec) { + tmp.clear(); + tmp.set_executor(exec); + } + auto local_result = make_temporary_clone(exec, result); + auto dense_res = make_temporary_conversion>( + local_result.get()); + exec->run(dense::make_compute_infinite_norm(this, dense_res.get(), tmp)); +} + + template void Dense::compute_norm2_impl(LinOp* result) const { diff --git a/core/matrix/dense_kernels.hpp b/core/matrix/dense_kernels.hpp index d785fc4a45e..f4d534731d6 100644 --- a/core/matrix/dense_kernels.hpp +++ b/core/matrix/dense_kernels.hpp @@ -109,6 +109,12 @@ namespace kernels { matrix::Dense>* result, \ array& tmp) +#define GKO_DECLARE_DENSE_COMPUTE_INFINITE_NORM_KERNEL(_type) \ + void compute_infinite_norm(std::shared_ptr exec, \ + const matrix::Dense<_type>* x, \ + matrix::Dense>* result, \ + array& tmp) + #define GKO_DECLARE_DENSE_COMPUTE_NORM1_KERNEL(_type) \ void compute_norm1(std::shared_ptr exec, \ const matrix::Dense<_type>* x, \ @@ -384,6 +390,8 @@ namespace kernels { template \ GKO_DECLARE_DENSE_COMPUTE_NORM2_DISPATCH_KERNEL(ValueType); \ template \ + GKO_DECLARE_DENSE_COMPUTE_INFINITE_NORM_KERNEL(ValueType); \ + template \ GKO_DECLARE_DENSE_COMPUTE_NORM1_KERNEL(ValueType); \ template \ GKO_DECLARE_DENSE_COMPUTE_MEAN_KERNEL(ValueType); \ diff --git a/core/solver/ir.cpp b/core/solver/ir.cpp index 92e5c0e4081..7d0f07735ff 100644 --- a/core/solver/ir.cpp +++ b/core/solver/ir.cpp @@ -292,7 +292,7 @@ void Ir::apply_dense_impl(const VectorType* dense_b, // solver_->apply(relaxation_factor_, residual_ptr, one_op, // dense_x); // WARNING: ignore the relaxation factor now - residual_ptr->compute_norm2(norm_op, reduction_tmp); + residual_ptr->compute_infinite_norm(norm_op, reduction_tmp); residual_ptr->inv_scale(norm_op); solver_->apply(residual_ptr, inner_solution); dense_x->add_scaled(norm_op, inner_solution); diff --git a/include/ginkgo/core/matrix/dense.hpp b/include/ginkgo/core/matrix/dense.hpp index 232d92c7702..654dd72ea35 100644 --- a/include/ginkgo/core/matrix/dense.hpp +++ b/include/ginkgo/core/matrix/dense.hpp @@ -1037,6 +1037,27 @@ class Dense */ void compute_norm2(ptr_param result, array& tmp) const; + /** + * Computes the column-wise infinite norm of this matrix. + * + * @param result a Dense row vector, used to store the norm + * (the number of columns in the vector must match the number + * of columns of this) + */ + void compute_infinite_norm(ptr_param result) const; + + /** + * Computes the column-wise infinite norm of this matrix. + * + * @param result a Dense row vector, used to store the norm + * (the number of columns in the vector must match the + * number of columns of this) + * @param tmp the temporary storage to use for partial sums during the + * reduction computation. It may be resized and/or reset to the + * correct executor. + */ + void compute_infinite_norm(ptr_param result, array& tmp) const; + /** * Computes the column-wise (L^1) norm of this matrix. * diff --git a/reference/matrix/dense_kernels.cpp b/reference/matrix/dense_kernels.cpp index 53773a131fe..01ed275b81d 100644 --- a/reference/matrix/dense_kernels.cpp +++ b/reference/matrix/dense_kernels.cpp @@ -366,6 +366,26 @@ void compute_norm1(std::shared_ptr exec, GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE(GKO_DECLARE_DENSE_COMPUTE_NORM1_KERNEL); +template +void compute_infinite_norm(std::shared_ptr exec, + const matrix::Dense* x, + matrix::Dense>* result, + array&) +{ + for (size_type j = 0; j < x->get_size()[1]; ++j) { + result->at(0, j) = zero>(); + } + for (size_type i = 0; i < x->get_size()[0]; ++i) { + for (size_type j = 0; j < x->get_size()[1]; ++j) { + result->at(0, j) = max(result->at(0, j), abs(x->at(i, j))); + } + } +} + +GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE( + GKO_DECLARE_DENSE_COMPUTE_INFINITE_NORM_KERNEL); + + template void compute_mean(std::shared_ptr exec, const matrix::Dense* x,