diff --git a/common/unified/CMakeLists.txt b/common/unified/CMakeLists.txt index 726c05b45ec..ccd9f7c69d8 100644 --- a/common/unified/CMakeLists.txt +++ b/common/unified/CMakeLists.txt @@ -25,7 +25,6 @@ set(UNIFIED_SOURCES solver/bicgstab_kernels.cpp solver/cg_kernels.cpp solver/cgs_kernels.cpp - solver/cgs_kernels.cpp solver/chebyshev_kernels.cpp solver/common_gmres_kernels.cpp solver/fcg_kernels.cpp diff --git a/common/unified/solver/chebyshev_kernels.cpp b/common/unified/solver/chebyshev_kernels.cpp index e4d945d2a32..dc0045d136b 100644 --- a/common/unified/solver/chebyshev_kernels.cpp +++ b/common/unified/solver/chebyshev_kernels.cpp @@ -4,6 +4,8 @@ #include "core/solver/chebyshev_kernels.hpp" +#include + #include #include "common/unified/base/kernel_launch.hpp" @@ -15,48 +17,94 @@ namespace GKO_DEVICE_NAMESPACE { namespace chebyshev { -template +template +using coeff_type = gko::kernels::chebyshev::coeff_type; + + +#if GINKGO_DPCPP_SINGLE_MODE + +// we only change type in device code to keep the interface is the same as the +// other backend. +template +using if_single_only_type = + std::conditional_t, float, + std::complex>; + + +#else + + +template +struct type_identity { + using type = T; +}; + + +template +using if_single_only_type = typename type_identity::type; + + +#endif + + +template void init_update(std::shared_ptr exec, - const ScalarType alpha, + const coeff_type alpha, const matrix::Dense* inner_sol, matrix::Dense* update_sol, matrix::Dense* output) { + using actual_coeff_type = if_single_only_type>; + using type = device_type; + + auto alpha_val = static_cast(alpha); + run_kernel( exec, [] GKO_KERNEL(auto row, auto col, auto alpha, auto inner_sol, auto update_sol, auto output) { - const auto inner_val = inner_sol(row, col); - update_sol(row, col) = inner_val; - output(row, col) += alpha * inner_val; + const auto inner_val = static_cast(inner_sol(row, col)); + update_sol(row, col) = + static_cast>(inner_val); + output(row, col) = static_cast>( + static_cast(output(row, col)) + + static_cast(alpha) * inner_val); }, - output->get_size(), alpha, inner_sol, update_sol, output); + output->get_size(), alpha_val, inner_sol, update_sol, output); } -GKO_INSTANTIATE_FOR_EACH_VALUE_AND_SCALAR_TYPE( - GKO_DECLARE_CHEBYSHEV_INIT_UPDATE_KERNEL); +GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE(GKO_DECLARE_CHEBYSHEV_INIT_UPDATE_KERNEL); -template +template void update(std::shared_ptr exec, const ScalarType alpha, const ScalarType beta, matrix::Dense* inner_sol, matrix::Dense* update_sol, matrix::Dense* output) { + using actual_coeff_type = if_single_only_type>; + using type = device_type; + + auto alpha_val = static_cast(alpha); + auto beta_val = static_cast(beta); + run_kernel( exec, [] GKO_KERNEL(auto row, auto col, auto alpha, auto beta, auto inner_sol, auto update_sol, auto output) { - const auto val = inner_sol(row, col) + beta * update_sol(row, col); - inner_sol(row, col) = val; - update_sol(row, col) = val; - output(row, col) += alpha * val; + const auto val = static_cast(inner_sol(row, col)) + + static_cast(beta) * + static_cast(update_sol(row, col)); + inner_sol(row, col) = static_cast>(val); + update_sol(row, col) = static_cast>(val); + output(row, col) = static_cast>( + static_cast(output(row, col)) + + static_cast(alpha) * val); }, - output->get_size(), alpha, beta, inner_sol, update_sol, output); + output->get_size(), alpha_val, beta_val, inner_sol, update_sol, output); } -GKO_INSTANTIATE_FOR_EACH_VALUE_AND_SCALAR_TYPE( - GKO_DECLARE_CHEBYSHEV_UPDATE_KERNEL); +GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE(GKO_DECLARE_CHEBYSHEV_UPDATE_KERNEL); } // namespace chebyshev diff --git a/core/device_hooks/common_kernels.inc.cpp b/core/device_hooks/common_kernels.inc.cpp index c1976434db3..8faf4fd12ba 100644 --- a/core/device_hooks/common_kernels.inc.cpp +++ b/core/device_hooks/common_kernels.inc.cpp @@ -678,8 +678,8 @@ GKO_STUB_CB_GMRES_CONST(GKO_DECLARE_CB_GMRES_SOLVE_KRYLOV_KERNEL); namespace chebyshev { -GKO_STUB_VALUE_AND_SCALAR_TYPE(GKO_DECLARE_CHEBYSHEV_INIT_UPDATE_KERNEL); -GKO_STUB_VALUE_AND_SCALAR_TYPE(GKO_DECLARE_CHEBYSHEV_UPDATE_KERNEL); +GKO_STUB_VALUE_TYPE(GKO_DECLARE_CHEBYSHEV_INIT_UPDATE_KERNEL); +GKO_STUB_VALUE_TYPE(GKO_DECLARE_CHEBYSHEV_UPDATE_KERNEL); } // namespace chebyshev diff --git a/core/solver/chebyshev.cpp b/core/solver/chebyshev.cpp index b5839cbe4d6..409204d60b5 100644 --- a/core/solver/chebyshev.cpp +++ b/core/solver/chebyshev.cpp @@ -173,6 +173,7 @@ void Chebyshev::apply_dense_impl(const VectorType* dense_b, { using Vector = matrix::Dense; using ws = workspace_traits; + using coeff_type = detail::coeff_type; auto exec = this->get_executor(); this->setup_workspace(); @@ -183,8 +184,8 @@ void Chebyshev::apply_dense_impl(const VectorType* dense_b, GKO_SOLVER_ONE_MINUS_ONE(); - auto alpha_ref = ValueType{1} / center_; - auto beta_ref = ValueType{0.5} * (foci_direction_ * alpha_ref) * + auto alpha_ref = coeff_type{1} / center_; + auto beta_ref = coeff_type{0.5} * (foci_direction_ * alpha_ref) * (foci_direction_ * alpha_ref); auto& stop_status = this->template create_workspace_array( @@ -239,10 +240,10 @@ void Chebyshev::apply_dense_impl(const VectorType* dense_b, } // beta_ref for iter == 1 is initialized in the beginning if (iter > 1) { - beta_ref = (foci_direction_ * alpha_ref / ValueType{2.0}) * - (foci_direction_ * alpha_ref / ValueType{2.0}); + beta_ref = (foci_direction_ * alpha_ref / coeff_type{2.0}) * + (foci_direction_ * alpha_ref / coeff_type{2.0}); } - alpha_ref = ValueType{1.0} / (center_ - beta_ref / alpha_ref); + alpha_ref = coeff_type{1.0} / (center_ - beta_ref / alpha_ref); // z = z + beta * p // p = z // x += alpha * p diff --git a/core/solver/chebyshev_kernels.hpp b/core/solver/chebyshev_kernels.hpp index f1557369eb2..1f8f67c32d5 100644 --- a/core/solver/chebyshev_kernels.hpp +++ b/core/solver/chebyshev_kernels.hpp @@ -20,25 +20,31 @@ namespace kernels { namespace chebyshev { -#define GKO_DECLARE_CHEBYSHEV_INIT_UPDATE_KERNEL(ValueType, ScalarType) \ - void init_update(std::shared_ptr exec, \ - const ScalarType alpha, \ - const matrix::Dense* inner_sol, \ - matrix::Dense* update_sol, \ +template +using coeff_type = + std::conditional_t, std::complex, double>; + + +#define GKO_DECLARE_CHEBYSHEV_INIT_UPDATE_KERNEL(ValueType) \ + void init_update(std::shared_ptr exec, \ + const coeff_type alpha, \ + const matrix::Dense* inner_sol, \ + matrix::Dense* update_sol, \ matrix::Dense* output) -#define GKO_DECLARE_CHEBYSHEV_UPDATE_KERNEL(ValueType, ScalarType) \ - void update(std::shared_ptr exec, \ - const ScalarType alpha, const ScalarType beta, \ - matrix::Dense* inner_sol, \ - matrix::Dense* update_sol, \ +#define GKO_DECLARE_CHEBYSHEV_UPDATE_KERNEL(ValueType) \ + void update(std::shared_ptr exec, \ + const coeff_type alpha, \ + const coeff_type beta, \ + matrix::Dense* inner_sol, \ + matrix::Dense* update_sol, \ matrix::Dense* output) -#define GKO_DECLARE_ALL_AS_TEMPLATES \ - template \ - GKO_DECLARE_CHEBYSHEV_INIT_UPDATE_KERNEL(ValueType, ScalarType); \ - template \ - GKO_DECLARE_CHEBYSHEV_UPDATE_KERNEL(ValueType, ScalarType) +#define GKO_DECLARE_ALL_AS_TEMPLATES \ + template \ + GKO_DECLARE_CHEBYSHEV_INIT_UPDATE_KERNEL(ValueType); \ + template \ + GKO_DECLARE_CHEBYSHEV_UPDATE_KERNEL(ValueType) } // namespace chebyshev diff --git a/include/ginkgo/core/solver/chebyshev.hpp b/include/ginkgo/core/solver/chebyshev.hpp index 18c979b0741..890becedde6 100644 --- a/include/ginkgo/core/solver/chebyshev.hpp +++ b/include/ginkgo/core/solver/chebyshev.hpp @@ -23,8 +23,16 @@ namespace gko { namespace solver { +namespace detail { +template +using coeff_type = + std::conditional_t, std::complex, double>; + + +} + /** * Chebyshev iteration is an iterative method for solving nonsymmetric problems * based on some knowledge of the spectrum of the (preconditioned) system @@ -121,8 +129,11 @@ class Chebyshev final * preconditioned system. It is usually be {lower bound of eigval, upper * bound of eigval} of preconditioned real matrices. */ - std::pair GKO_FACTORY_PARAMETER_VECTOR( - foci, value_type{0}, value_type{1}); + std::pair, + detail::coeff_type> + GKO_FACTORY_PARAMETER_VECTOR(foci, + detail::coeff_type{0}, + detail::coeff_type{1}); /** * Default initial guess mode. The available options are under @@ -170,9 +181,6 @@ class Chebyshev final const LinOp* beta, LinOp* x, initial_guess_mode guess) const override; - void set_relaxation_factor( - std::shared_ptr> new_factor); - explicit Chebyshev(std::shared_ptr exec) : EnableLinOp(std::move(exec)) {} @@ -182,8 +190,8 @@ class Chebyshev final private: std::shared_ptr solver_{}; - ValueType center_; - ValueType foci_direction_; + detail::coeff_type center_; + detail::coeff_type foci_direction_; }; diff --git a/reference/solver/chebyshev_kernels.cpp b/reference/solver/chebyshev_kernels.cpp index 2adf0a8026d..a6cfddec2f1 100644 --- a/reference/solver/chebyshev_kernels.cpp +++ b/reference/solver/chebyshev_kernels.cpp @@ -12,45 +12,55 @@ namespace reference { namespace chebyshev { -template +template +using coeff_type = gko::kernels::chebyshev::coeff_type; + + +template void init_update(std::shared_ptr exec, - const ScalarType alpha, + const coeff_type alpha, const matrix::Dense* inner_sol, matrix::Dense* update_sol, matrix::Dense* output) { + using type = coeff_type; for (size_t row = 0; row < output->get_size()[0]; row++) { for (size_t col = 0; col < output->get_size()[1]; col++) { - const auto inner_val = inner_sol->at(row, col); - update_sol->at(row, col) = inner_val; - output->at(row, col) += alpha * inner_val; + const auto inner_val = static_cast(inner_sol->at(row, col)); + update_sol->at(row, col) = static_cast(inner_val); + output->at(row, col) = + static_cast(static_cast(output->at(row, col)) + + static_cast(alpha) * inner_val); } } } -GKO_INSTANTIATE_FOR_EACH_VALUE_AND_SCALAR_TYPE( - GKO_DECLARE_CHEBYSHEV_INIT_UPDATE_KERNEL); +GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE(GKO_DECLARE_CHEBYSHEV_INIT_UPDATE_KERNEL); -template -void update(std::shared_ptr exec, const ScalarType alpha, - const ScalarType beta, matrix::Dense* inner_sol, +template +void update(std::shared_ptr exec, + const coeff_type alpha, const coeff_type beta, + matrix::Dense* inner_sol, matrix::Dense* update_sol, matrix::Dense* output) { + using type = coeff_type; for (size_t row = 0; row < output->get_size()[0]; row++) { for (size_t col = 0; col < output->get_size()[1]; col++) { - const auto val = - inner_sol->at(row, col) + beta * update_sol->at(row, col); - inner_sol->at(row, col) = val; - update_sol->at(row, col) = val; - output->at(row, col) += alpha * val; + const auto val = static_cast(inner_sol->at(row, col)) + + static_cast(beta) * + static_cast(update_sol->at(row, col)); + inner_sol->at(row, col) = static_cast(val); + update_sol->at(row, col) = static_cast(val); + output->at(row, col) = + static_cast(static_cast(output->at(row, col)) + + static_cast(alpha) * val); } } } -GKO_INSTANTIATE_FOR_EACH_VALUE_AND_SCALAR_TYPE( - GKO_DECLARE_CHEBYSHEV_UPDATE_KERNEL); +GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE(GKO_DECLARE_CHEBYSHEV_UPDATE_KERNEL); } // namespace chebyshev