From 95b25f286cc4761b1192fa6c12386a5e1d02dd7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Chevalier?= Date: Thu, 16 Nov 2023 10:41:26 +0100 Subject: [PATCH] Hypre directbuilder (#189) * [hypre]: Introduce HypreDirectBuilder * [move]: refactor DirectMatrixBuilder Use composition instead of inheritance. * [ref]: refactor DirectMatrixBuilder Use composition instead of inheritance. * [all]: clang-format * [core]: some cleaning * [all]: IDirectMatrixBuilder and factory Should be able to use hypre directly, without SimpleCSR. * [hypre]: clang-format * [all]: real factory for DirectMatrixBuilder * [all]: change default DirectMatrixBuilder * [move]: add method to choose DirectMatrixBuilder backend * [dok]: make DokBuilder implements IDirectMatrixBuilder * [all]: add contribute method to IDirectMatrixBuilder This method returns whether or not the non zero was added. * [move]: Remove DoKDirectMatrixBuilder The functionality can be accessed with new DirectMatrixBuilder. * [core]: Add missing header for IDirectMatrixBuilder * [hypre]: Correct reset for DirectMatrixBuilder * [dok]: reset flag for DirectMatrixBuilder * [hypre] directbuilder works with reset flags * [hypre] Call ClearAllErrors before major operations * [dok] fix format --- CHANGELOG.md | 1 + plugins/hypre/CMakeLists.txt | 14 +- plugins/hypre/bench/CMakeLists.txt | 2 +- .../examples/hypre_example_solve_move.cpp | 16 +- .../converters/simplecsr_to_hypre_matrix.cpp | 5 +- .../hypre/src/hypre_direct_matrix_builder.cpp | 86 +++++++++ .../hypre/src/hypre_direct_matrix_builder.h | 143 ++++++++++++++ plugins/hypre/src/hypre_instance.cpp | 7 +- plugins/hypre/src/hypre_matrix.cpp | 81 ++++++-- plugins/hypre/src/hypre_matrix.h | 16 +- plugins/hypre/tests/CMakeLists.txt | 2 +- plugins/hypre/tests/move_use.cpp | 2 +- src/core/CMakeLists.txt | 81 ++++---- src/core/alien/Alien.h | 2 +- src/core/alien/core/impl/MultiMatrixImpl.h | 175 +++++++++--------- .../handlers/scalar/IDirectMatrixBuilder.h | 114 ++++++++++++ .../handlers/scalar/MatrixBuilderFactory.cpp | 54 ++++++ .../handlers/scalar/MatrixBuilderFactory.h | 76 ++++++++ src/core/alien/import_export/Reader.h | 8 +- .../dok/BaseDoKDirectMatrixBuilder.cpp | 45 ++++- .../kernels/dok/BaseDoKDirectMatrixBuilder.h | 70 ++++++- src/core/alien/kernels/dok/DoKLocalMatrixT.h | 23 +-- src/core/alien/kernels/dok/DoKMatrixT.h | 16 +- .../alien/kernels/simple_csr/CMakeLists.txt | 2 + .../SimpleCSRDirectMatrixBuilder.cpp} | 83 +++++---- .../SimpleCSRDirectMatrixBuilder.h} | 119 ++++++------ src/movesemantic/CMakeLists.txt | 9 +- .../handlers/scalar/DirectMatrixBuilder.h | 112 +++++++++-- .../handlers/scalar/DoKDirectMatrixBuilder.h | 69 ------- .../alien/move/impl/MatrixMarketReader.cc | 6 +- .../tests/TestDoKDirectMatrixBuilder.cc | 7 +- .../ref/handlers/scalar/DirectMatrixBuilder.h | 87 ++++++++- 32 files changed, 1137 insertions(+), 396 deletions(-) create mode 100644 plugins/hypre/src/hypre_direct_matrix_builder.cpp create mode 100644 plugins/hypre/src/hypre_direct_matrix_builder.h create mode 100644 src/core/alien/handlers/scalar/IDirectMatrixBuilder.h create mode 100644 src/core/alien/handlers/scalar/MatrixBuilderFactory.cpp create mode 100644 src/core/alien/handlers/scalar/MatrixBuilderFactory.h rename src/core/alien/{handlers/scalar/BaseDirectMatrixBuilder.cc => kernels/simple_csr/SimpleCSRDirectMatrixBuilder.cpp} (90%) rename src/core/alien/{handlers/scalar/BaseDirectMatrixBuilder.h => kernels/simple_csr/SimpleCSRDirectMatrixBuilder.h} (69%) delete mode 100644 src/movesemantic/alien/move/handlers/scalar/DoKDirectMatrixBuilder.h diff --git a/CHANGELOG.md b/CHANGELOG.md index ee2f8dc86..fff60d0d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - \[move\]: parallel matrix-market reader - \[hypre\]: improve AMG parameter choices, especially for GPU - \[trilinos\]: use modern CMake Trilinos and support for GPU +- \[all\]: New infra to choose the implementation backend for `DirectMatrixBuilder` **Fixed bugs:** diff --git a/plugins/hypre/CMakeLists.txt b/plugins/hypre/CMakeLists.txt index ecfcf1f90..0f2f5cf94 100644 --- a/plugins/hypre/CMakeLists.txt +++ b/plugins/hypre/CMakeLists.txt @@ -52,6 +52,8 @@ add_library(hypre_wrapper src/hypre_linear_solver.cpp src/hypre_instance.h src/hypre_instance.cpp + src/hypre_direct_matrix_builder.cpp + src/hypre_direct_matrix_builder.h src/converters/hypre_to_simplecsr_vector.cpp src/converters/simplecsr_to_hypre_vector.cpp src/converters/simplecsr_to_hypre_matrix.cpp @@ -72,7 +74,7 @@ endif () target_link_libraries(hypre_wrapper PUBLIC Alien::alien_core - ) +) target_link_libraries(hypre_wrapper PRIVATE MPI::MPI_CXX @@ -81,13 +83,13 @@ target_link_libraries(hypre_wrapper PRIVATE Arccore::arccore_base Arccore::arccore_message_passing_mpi arccon::Hypre - ) +) target_include_directories(hypre_wrapper PUBLIC $ $ $ - ) +) add_library(Alien::hypre_wrapper ALIAS hypre_wrapper) @@ -96,7 +98,7 @@ include(GenerateExportHeader) generate_export_header(hypre_wrapper BASE_NAME ALIEN_HYPRE EXPORT_FILE_NAME include/alien/hypre/export.h - ) +) # Examples set(ALIEN_BENCHMARK ON) @@ -117,12 +119,12 @@ set(ALIENHYPRE_EXPORT_TARGET ${PROJECT_NAME}Targets) install(DIRECTORY include/alien/hypre DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/alien - ) +) install(TARGETS hypre_wrapper EXPORT ${ALIENHYPRE_EXPORT_TARGET} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) +) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/include/alien/hypre/export.h diff --git a/plugins/hypre/bench/CMakeLists.txt b/plugins/hypre/bench/CMakeLists.txt index 65f83686f..dd2cdf13d 100644 --- a/plugins/hypre/bench/CMakeLists.txt +++ b/plugins/hypre/bench/CMakeLists.txt @@ -33,7 +33,7 @@ include(GNUInstallDirs) install(TARGETS bench_hypre EXPORT Alien RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ) +) if (ALIEN_UNIT_TESTS) diff --git a/plugins/hypre/examples/hypre_example_solve_move.cpp b/plugins/hypre/examples/hypre_example_solve_move.cpp index c8e4350e8..0a501a2ef 100644 --- a/plugins/hypre/examples/hypre_example_solve_move.cpp +++ b/plugins/hypre/examples/hypre_example_solve_move.cpp @@ -54,7 +54,7 @@ int test() tm->info() << "build matrix with direct matrix builder"; { - Alien::Move::DirectMatrixBuilder builder(std::move(A), Alien::DirectMatrixOptions::eResetValues); + Alien::Move::DirectMatrixBuilder builder(std::move(A), Alien::DirectMatrixOptions::eResetProfile, Alien::DirectMatrixOptions::eSymmetric, std::make_optional(Alien::AlgebraTraits::name())); builder.reserve(3); // Réservation de 3 coefficients par ligne builder.allocate(); // Allocation de l'espace mémoire réservé @@ -132,6 +132,20 @@ int test() tm->info() << " => ||r|| = " << norm; + // Try to change matrix values + { + Alien::Move::DirectMatrixBuilder builder(std::move(A), Alien::DirectMatrixOptions::eResetValues, Alien::DirectMatrixOptions::eSymmetric, std::make_optional(Alien::AlgebraTraits::name())); + + for (int irow = offset; irow < offset + lsize; ++irow) { + builder(irow, irow) = 4.; + if (irow - 1 >= 0) + builder(irow, irow - 1) = -2.; + if (irow + 1 < gsize) + builder(irow, irow + 1) = -2.; + } + A = builder.release(); + } + tm->info() << " "; tm->info() << "... example finished !!!"; diff --git a/plugins/hypre/src/converters/simplecsr_to_hypre_matrix.cpp b/plugins/hypre/src/converters/simplecsr_to_hypre_matrix.cpp index afd6c82bd..6e977b7c5 100644 --- a/plugins/hypre/src/converters/simplecsr_to_hypre_matrix.cpp +++ b/plugins/hypre/src/converters/simplecsr_to_hypre_matrix.cpp @@ -47,7 +47,8 @@ class SimpleCSR_to_Hypre_MatrixConverter final : public Alien::IMatrixConverter void _build(const Alien::SimpleCSRMatrix& sourceImpl, Alien::Hypre::Matrix& targetImpl) const; - void _buildBlock(const Alien::SimpleCSRMatrix& sourceImpl, Alien::Hypre::Matrix& targetImpl) const; + void + _buildBlock(const Alien::SimpleCSRMatrix& sourceImpl, Alien::Hypre::Matrix& targetImpl) const; }; void SimpleCSR_to_Hypre_MatrixConverter::convert(const IMatrixImpl* sourceImpl, IMatrixImpl* targetImpl) const @@ -90,7 +91,7 @@ void SimpleCSR_to_Hypre_MatrixConverter::_build(const Alien::SimpleCSRMatrix +#include + +#include + +namespace Alien::Hypre +{ +HypreDirectMatrixBuilder::HypreDirectMatrixBuilder(Alien::IMatrix& matrix, + Hypre::HypreDirectMatrixBuilder::ResetFlag reset_flag, + [[maybe_unused]] Hypre::HypreDirectMatrixBuilder::SymmetricFlag symmetric_flag) +: m_matrix(matrix) +{ + + m_matrix.impl()->lock(); + m_matrix_impl = &m_matrix.impl()->get(true); + + m_matrix_impl->init(reset_flag); +} + +void HypreDirectMatrixBuilder::finalize() +{ + m_matrix_impl->assemble(); + m_matrix.impl()->unlock(); +} + +void HypreDirectMatrixBuilder::setData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) +{ + m_matrix_impl->setRowValues(iIndex, ConstArrayView(1, &jIndex), ConstArrayView(1, &value)); +} + +void HypreDirectMatrixBuilder::setData(Arccore::Integer iIndex, Arccore::Real factor, + Arccore::ConstArrayView jIndexes, + Arccore::ConstArrayView jValues) +{ + if (factor != 1.0) { + throw FatalErrorException("Scaling is not supported"); + } + + m_matrix_impl->setRowValues(iIndex, jIndexes, jValues); +} + +void HypreDirectMatrixBuilder::addData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) +{ + m_matrix_impl->addRowValues(iIndex, ConstArrayView(1, &jIndex), ConstArrayView(1, &value)); +} + +void HypreDirectMatrixBuilder::addData(Arccore::Integer iIndex, Arccore::Real factor, + Arccore::ConstArrayView jIndexes, + Arccore::ConstArrayView jValues) +{ + if (factor != 1.0) { + throw FatalErrorException("Scaling is not supported"); + } + + m_matrix_impl->addRowValues(iIndex, jIndexes, jValues); +} + +const ALIEN_HYPRE_EXPORT Alien::Common::MatrixBuilderFactory hypre_builder_register( +AlgebraTraits::name(), [](IMatrix& matrix, DirectMatrixOptions::ResetFlag reset, DirectMatrixOptions::SymmetricFlag symmetry) { return std::make_unique(matrix, reset, symmetry); }); + +}; // namespace Alien::Hypre diff --git a/plugins/hypre/src/hypre_direct_matrix_builder.h b/plugins/hypre/src/hypre_direct_matrix_builder.h new file mode 100644 index 000000000..013c31634 --- /dev/null +++ b/plugins/hypre/src/hypre_direct_matrix_builder.h @@ -0,0 +1,143 @@ +/* + * Copyright 2023 IFPEN-CEA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// +// Created by chevalierc on 17/05/23. +// + +#ifndef ALIEN_HYPREDIRECTMATRIXBUILDER_H +#define ALIEN_HYPREDIRECTMATRIXBUILDER_H + +#include +#include + +#include +#include + +#include +#include "hypre_matrix.h" + +namespace Alien +{ + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +namespace Hypre +{ + + /*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*/ + + class ALIEN_EXPORT HypreDirectMatrixBuilder final : public Alien::Common::IDirectMatrixBuilder + { + public: + using ResetFlag = DirectMatrixOptions::ResetFlag; + using ReserveFlag = DirectMatrixOptions::ReserveFlag; + using SymmetricFlag = DirectMatrixOptions::SymmetricFlag; + + using MatrixElement = MatrixElementT; + + HypreDirectMatrixBuilder(IMatrix& matrix, [[maybe_unused]] ResetFlag reset_flag, + [[maybe_unused]] SymmetricFlag symmetric_flag = SymmetricFlag::eSymmetric); + + ~HypreDirectMatrixBuilder() override + { + finalize(); + } + + HypreDirectMatrixBuilder(HypreDirectMatrixBuilder&) = delete; + + HypreDirectMatrixBuilder(HypreDirectMatrixBuilder&&) = delete; + + HypreDirectMatrixBuilder& operator=(const HypreDirectMatrixBuilder&) = delete; + + HypreDirectMatrixBuilder& operator=(HypreDirectMatrixBuilder&&) = delete; + + void reserve(Arccore::Integer n, ReserveFlag flag = ReserveFlag::eResetReservation) override + { + // Nothing yet + } + + void reserve(Arccore::ConstArrayView indices, Arccore::Integer n, + ReserveFlag flag = ReserveFlag::eResetReservation) override + { + // Nothing yet + } + + void allocate() override + { + // Nothing yet + } + + void addData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) override; + + void addData(Arccore::Integer iIndex, Arccore::Real factor, + Arccore::ConstArrayView jIndexes, + Arccore::ConstArrayView jValues) override; + + void setData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) override; + + void setData(Arccore::Integer iIndex, Arccore::Real factor, + Arccore::ConstArrayView jIndexes, + Arccore::ConstArrayView jValues) override; + + void finalize() override; + + void squeeze() override + { + // do nothing + } + + [[nodiscard]] Arccore::String stats() const override + { + // Do nothing + return { "" }; + } + + [[nodiscard]] Arccore::String stats(Arccore::IntegerConstArrayView ids) const override + { + // Do nothing + return { "" }; + } + std::optional contribute(Arccore::Integer row, Arccore::Integer col, Arccore::Real value) override + { + addData(row, col, value); + return { value }; + } + + private: + IMatrix& m_matrix; + + Matrix* m_matrix_impl; + }; + + /*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*/ + +} // namespace Hypre + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +} // namespace Alien + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +#endif //ALIEN_HYPREDIRECTMATRIXBUILDER_H diff --git a/plugins/hypre/src/hypre_instance.cpp b/plugins/hypre/src/hypre_instance.cpp index 57b5bdd82..67c731b6f 100644 --- a/plugins/hypre/src/hypre_instance.cpp +++ b/plugins/hypre/src/hypre_instance.cpp @@ -31,8 +31,11 @@ class AlienHypreInstance public: static void init_if_needed(MPI_Comm comm) { - if (hypre_initialized) + if (hypre_initialized) { + // Clear all Hypre error for this session + HYPRE_ClearAllErrors(); return; + } bind_devices(comm); @@ -41,8 +44,10 @@ class AlienHypreInstance #endif hypre_initialized = true; + HYPRE_ClearAllErrors(); setup_devices(); + HYPRE_ClearAllErrors(); } static void bind_devices([[maybe_unused]] MPI_Comm comm) diff --git a/plugins/hypre/src/hypre_matrix.cpp b/plugins/hypre/src/hypre_matrix.cpp index f53e440a6..e1effeba7 100644 --- a/plugins/hypre/src/hypre_matrix.cpp +++ b/plugins/hypre/src/hypre_matrix.cpp @@ -46,7 +46,8 @@ namespace class ArccoreHypreBufferConverter { public: - template explicit ArccoreHypreBufferConverter(ArccoreArray array) + template + explicit ArccoreHypreBufferConverter(ArccoreArray array) : ptr(array.data()) { assert(sizeof(typename ArccoreArray::value_type) == sizeof(HypreType)); @@ -67,13 +68,16 @@ namespace } ~ArccoreHypreBufferConverter() +#ifndef ALIEN_HYPRE_DEVICE + = default; + +#else { -#ifdef ALIEN_HYPRE_DEVICE if (memory_location != HYPRE_MEMORY_HOST) { hypre_TFree(ptr, memory_location); } -#endif // ALIEN_HYPRE_DEVICE } +#endif // ALIEN_HYPRE_DEVICE private: HypreType* ptr = nullptr; @@ -92,8 +96,7 @@ Matrix::Matrix(const MultiMatrixImpl* multi_impl) hypre_init_if_needed(m_comm); const auto& row_space = multi_impl->rowSpace(); - const auto& col_space = multi_impl->colSpace(); - if (row_space.size() != col_space.size()) + if (const auto& col_space = multi_impl->colSpace(); row_space.size() != col_space.size()) throw Arccore::FatalErrorException("Hypre matrix must be square"); init(); @@ -105,13 +108,35 @@ Matrix::~Matrix() HYPRE_IJMatrixDestroy(m_hypre); } -void Matrix::init() +void Matrix::init(DirectMatrixOptions::ResetFlag reset_flag) { - auto ilower = this->distribution().rowOffset(); - auto iupper = ilower + this->distribution().localRowSize() - 1; - auto ierr = HYPRE_IJMatrixCreate(m_comm, ilower, iupper, ilower, iupper, &m_hypre); - ierr |= HYPRE_IJMatrixSetObjectType(m_hypre, HYPRE_PARCSR); - ierr |= HYPRE_IJMatrixInitialize(m_hypre); + HYPRE_Int ierr = 0; + // Clear all Hypre error for this session + HYPRE_ClearAllErrors(); + + switch (reset_flag) { + case DirectMatrixOptions::eNoReset: + break; + case DirectMatrixOptions::eResetValues: + assemble(); + ierr |= HYPRE_IJMatrixSetConstantValues(m_hypre, 0); + break; + case DirectMatrixOptions::eResetProfile: + ierr |= HYPRE_IJMatrixInitialize(m_hypre); + break; + case DirectMatrixOptions::eResetAllocation: + if (m_hypre) { + HYPRE_IJMatrixDestroy(m_hypre); + m_hypre = nullptr; + } + auto ilower = this->distribution().rowOffset(); + auto iupper = ilower + this->distribution().localRowSize() - 1; + + ierr |= HYPRE_IJMatrixCreate(m_comm, ilower, iupper, ilower, iupper, &m_hypre); + ierr |= HYPRE_IJMatrixSetObjectType(m_hypre, HYPRE_PARCSR); + ierr |= HYPRE_IJMatrixInitialize(m_hypre); + break; + } if (ierr) { throw Arccore::FatalErrorException(A_FUNCINFO, "Hypre Initialisation failed"); @@ -120,9 +145,10 @@ void Matrix::init() void Matrix::setProfile(Arccore::ConstArrayView row_sizes) { - if (m_hypre) + if (m_hypre) { HYPRE_IJMatrixDestroy(m_hypre); - + m_hypre = nullptr; + } init(); if (HYPRE_IJMatrixSetRowSizes(m_hypre, row_sizes.data())) { throw Arccore::FatalErrorException(A_FUNCINFO, "Hypre set profile failed"); @@ -144,10 +170,12 @@ void Matrix::setRowValues(int row, Arccore::ConstArrayView cols, Arccore::C auto rows = ArrayView(1, &row); auto ncols = ArrayView(1, &one); - return setRowsValues(rows, ncols, cols, values); + return insertRowsValues(rows, ncols, cols, values, true); } -void Matrix::setRowsValues(Arccore::ConstArrayView rows, Arccore::ArrayView ncols, Arccore::ConstArrayView cols, Arccore::ConstArrayView values) +void Matrix::insertRowsValues(Arccore::ConstArrayView rows, Arccore::ArrayView ncols, + Arccore::ConstArrayView cols, + Arccore::ConstArrayView values, bool set) { // First, check parameters consistency if (rows.size() != ncols.size()) { @@ -167,7 +195,19 @@ void Matrix::setRowsValues(Arccore::ConstArrayView rows, Arccore::ArrayView auto hypre_rows = ArccoreHypreBufferConverter(rows); // Third call hypre. - auto ierr = HYPRE_IJMatrixSetValues(m_hypre, rows.size(), hypre_ncols.get(), hypre_rows.get(), hypre_cols.get(), hypre_values.get()); + auto hypre_insert = [&](auto inserter) { + return inserter(m_hypre, rows.size(), hypre_ncols.get(), hypre_rows.get(), hypre_cols.get(), + hypre_values.get()); + }; + + int ierr = 0; + + if (set) { + ierr = hypre_insert(HYPRE_IJMatrixSetValues); + } + else { + ierr = hypre_insert(HYPRE_IJMatrixAddToValues); + } if (ierr) { auto msg = Arccore::String::format("Cannot set Hypre Matrix Values"); @@ -175,4 +215,13 @@ void Matrix::setRowsValues(Arccore::ConstArrayView rows, Arccore::ArrayView } } +void Matrix::addRowValues(int row, Arccore::ConstArrayView cols, Arccore::ConstArrayView values) +{ + int one = 1; + auto rows = ArrayView(1, &row); + auto ncols = ArrayView(1, &one); + + return insertRowsValues(rows, ncols, cols, values, false); +} + } // namespace Alien::Hypre \ No newline at end of file diff --git a/plugins/hypre/src/hypre_matrix.h b/plugins/hypre/src/hypre_matrix.h index cd8d9ecd2..6d83f5957 100644 --- a/plugins/hypre/src/hypre_matrix.h +++ b/plugins/hypre/src/hypre_matrix.h @@ -21,6 +21,7 @@ #include #include +#include "alien/handlers/scalar/IDirectMatrixBuilder.h" namespace Alien::Hypre { @@ -37,6 +38,10 @@ class Matrix : public IMatrixImpl Arccore::ConstArrayView cols, Arccore::ConstArrayView values); + void addRowValues(int row, + Arccore::ConstArrayView cols, + Arccore::ConstArrayView values); + //! Fill several partial rows at the same time. //! Function strongly mimic `HYPRE_IJMatrixSetValues` semantic. //! @@ -48,18 +53,17 @@ class Matrix : public IMatrixImpl //! `rows` and `ncols` should have the same size. //! `cols` and `values` should have the same size. //! For Hypre to use OpenMP threads for set values, rows values must be unique. - void setRowsValues(Arccore::ConstArrayView rows, - Arccore::ArrayView ncols, - Arccore::ConstArrayView cols, - Arccore::ConstArrayView values); + void insertRowsValues(Arccore::ConstArrayView rows, Arccore::ArrayView ncols, + Arccore::ConstArrayView cols, + Arccore::ConstArrayView values, bool set = true); void assemble(); HYPRE_IJMatrix internal() const { return m_hypre; } - private: - void init(); + void init(DirectMatrixOptions::ResetFlag reset_flag = DirectMatrixOptions::ResetFlag::eResetAllocation); + private: HYPRE_IJMatrix m_hypre = nullptr; MPI_Comm m_comm; }; diff --git a/plugins/hypre/tests/CMakeLists.txt b/plugins/hypre/tests/CMakeLists.txt index 376ee78aa..a50052877 100644 --- a/plugins/hypre/tests/CMakeLists.txt +++ b/plugins/hypre/tests/CMakeLists.txt @@ -10,7 +10,7 @@ target_link_libraries(hypre_gtest PRIVATE Alien::alien_core Alien::alien_semantic_move Alien::alien_semantic_ref Alien::hypre_wrapper - ) +) include(LoadAlienTest) diff --git a/plugins/hypre/tests/move_use.cpp b/plugins/hypre/tests/move_use.cpp index 0b335df7e..6aadac083 100644 --- a/plugins/hypre/tests/move_use.cpp +++ b/plugins/hypre/tests/move_use.cpp @@ -51,7 +51,7 @@ class SimpleLinearProblemFixtureMove : public ::testing::Test { Alien::Move::DirectMatrixBuilder builder( - std::move(m_matrix), Alien::DirectMatrixOptions::eResetAllocation); + std::move(m_matrix), Alien::DirectMatrixOptions::eResetAllocation, Alien::DirectMatrixOptions::eSymmetric, std::make_optional(Alien::AlgebraTraits::name())); builder.reserve(3); // Réservation de 3 coefficients par ligne builder.allocate(); // Allocation de l'espace mémoire réservé diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 80f489144..7328f4996 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -22,10 +22,10 @@ add_subdirectory(alien/kernels/redistributor) add_subdirectory(alien/kernels/simple_csr) add_subdirectory(alien/index_manager) -IF(ALIEN_USE_SYCL) - find_package(hipSYCL CONFIG REQUIRED) - add_subdirectory(alien/kernels/sycl) -endif() +IF (ALIEN_USE_SYCL) + find_package(hipSYCL CONFIG REQUIRED) + add_subdirectory(alien/kernels/sycl) +endif () set(alien_core_list alien/Alien.h @@ -111,8 +111,9 @@ set(alien_core_list alien/handlers/profiler/BaseMatrixProfiler.cc alien/handlers/profiler/BaseMatrixProfiler.h alien/handlers/profiler/MatrixProfilerT.h - alien/handlers/scalar/BaseDirectMatrixBuilder.cc - alien/handlers/scalar/BaseDirectMatrixBuilder.h + alien/handlers/scalar/IDirectMatrixBuilder.h + alien/handlers/scalar/MatrixBuilderFactory.cpp + alien/handlers/scalar/MatrixBuilderFactory.h alien/handlers/scalar/BaseProfiledMatrixBuilder.cc alien/handlers/scalar/BaseProfiledMatrixBuilder.h alien/handlers/scalar/BaseVectorReader.cc @@ -124,28 +125,28 @@ set(alien_core_list alien/import_export/MatrixMarketSystemReader.h alien/import_export/MatrixMarketSystemReader.cc alien/import_export/Reader.h - ) +) if (LibArchive_FOUND) - list(APPEND alien_core_list - alien/import_export/SuiteSparseArchiveSystemReader.cc - alien/import_export/SuiteSparseArchiveSystemReader.h) + list(APPEND alien_core_list + alien/import_export/SuiteSparseArchiveSystemReader.cc + alien/import_export/SuiteSparseArchiveSystemReader.h) endif () add_library(alien_core ${alien_core_list}) target_link_libraries(alien_core PUBLIC alien_utils alien_data) target_link_libraries(alien_core PUBLIC - alien_kernel_dok - alien_kernel_composite - alien_kernel_redistributor - alien_kernel_simplecsr) + alien_kernel_dok + alien_kernel_composite + alien_kernel_redistributor + alien_kernel_simplecsr) target_link_libraries(alien_core PUBLIC alien_index_manager) -if(LibArchive_FOUND) - target_link_libraries(alien_core PUBLIC archive) +if (LibArchive_FOUND) + target_link_libraries(alien_core PUBLIC archive) endif () set_property(TARGET alien_core PROPERTY CXX_STANDARD 17) @@ -154,30 +155,30 @@ message(STATUS "Using AVX Simd instructions ? -> ${ALIEN_WANT_AVX}") message(STATUS "Using AVX2 Simd instructions ? -> ${ALIEN_WANT_AVX2}") message(STATUS "Using AVX512 Simd instructions ? -> ${ALIEN_WANT_AVX512}") -if(CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID STREQUAL Clang)) - if(ALIEN_WANT_AVX) - target_compile_options(alien_core INTERFACE -mavx) - endif() - if(ALIEN_WANT_AVX2) - target_compile_options(alien_core INTERFACE -mavx -mfma) - endif() - if(ALIEN_WANT_AVX512) - target_compile_options(alien_core INTERFACE -mavx512f -mavx512cd) - endif() -endif() - -IF(ALIEN_USE_SYCL) - target_link_libraries(alien_core PUBLIC alien_kernel_sycl) - target_compile_options(alien_core PRIVATE "--gcc-toolchain=${GCCCORE_ROOT}") - add_sycl_to_target(TARGET alien_core) -ENDIF() +if (CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID STREQUAL Clang)) + if (ALIEN_WANT_AVX) + target_compile_options(alien_core INTERFACE -mavx) + endif () + if (ALIEN_WANT_AVX2) + target_compile_options(alien_core INTERFACE -mavx -mfma) + endif () + if (ALIEN_WANT_AVX512) + target_compile_options(alien_core INTERFACE -mavx512f -mavx512cd) + endif () +endif () + +IF (ALIEN_USE_SYCL) + target_link_libraries(alien_core PUBLIC alien_kernel_sycl) + target_compile_options(alien_core PRIVATE "--gcc-toolchain=${GCCCORE_ROOT}") + add_sycl_to_target(TARGET alien_core) +ENDIF () target_link_libraries(alien_core PUBLIC - Arccore::arccore_trace - Arccore::arccore_collections - Arccore::arccore_base - Arccore::arccore_message_passing_mpi) + Arccore::arccore_trace + Arccore::arccore_collections + Arccore::arccore_base + Arccore::arccore_message_passing_mpi) find_package(Boost COMPONENTS program_options REQUIRED) @@ -195,17 +196,17 @@ target_link_libraries(alien_core PUBLIC alien_headers) install(DIRECTORY alien DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h" - ) +) install(TARGETS alien_core EXPORT ${ALIEN_EXPORT_TARGET} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) +) install(TARGETS alien_headers EXPORT ${ALIEN_EXPORT_TARGET} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) +) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/alien/AlienExport.h diff --git a/src/core/alien/Alien.h b/src/core/alien/Alien.h index 320d035c7..66386004f 100644 --- a/src/core/alien/Alien.h +++ b/src/core/alien/Alien.h @@ -55,7 +55,7 @@ #include "handlers/scalar/BaseVectorWriter.h" #include "handlers/profiler/BaseMatrixProfiler.h" -#include "handlers/scalar/BaseDirectMatrixBuilder.h" +#include "handlers/scalar/IDirectMatrixBuilder.h" #include "handlers/scalar/BaseProfiledMatrixBuilder.h" #include "functional/Cast.h" diff --git a/src/core/alien/core/impl/MultiMatrixImpl.h b/src/core/alien/core/impl/MultiMatrixImpl.h index 2eb6222a0..3671ea994 100644 --- a/src/core/alien/core/impl/MultiMatrixImpl.h +++ b/src/core/alien/core/impl/MultiMatrixImpl.h @@ -62,7 +62,8 @@ namespace Alien * While requesting a matrix in a specific format, if the up to date matrix is not in that * specific format, the up-to-date matrix will be converted, provided a converter exists. */ -class ALIEN_EXPORT MultiMatrixImpl : public TimestampMng +class ALIEN_EXPORT MultiMatrixImpl +: public TimestampMng , public UserFeatureMng , public ObjectWithTrace , public ObjectWithLock @@ -72,11 +73,11 @@ class ALIEN_EXPORT MultiMatrixImpl : public TimestampMng MultiMatrixImpl(); /*! - * \brief Constructor - * \param[in] row_space The row space of the matrix - * \param[in] col_space The column space of the matrix - * \param[in] dist The distribution of the matrix - */ + * \brief Constructor + * \param[in] row_space The row space of the matrix + * \param[in] col_space The column space of the matrix + * \param[in] dist The distribution of the matrix + */ MultiMatrixImpl(std::shared_ptr row_space, std::shared_ptr col_space, std::shared_ptr dist); @@ -85,125 +86,125 @@ class ALIEN_EXPORT MultiMatrixImpl : public TimestampMng protected: /*! - * \brief Copy constructor - * \param[in] impl The MultiMatrixImpl to copy - */ + * \brief Copy constructor + * \param[in] impl The MultiMatrixImpl to copy + */ MultiMatrixImpl(const MultiMatrixImpl& impl); public: /*! - * \brief Set uniform block information - * \param[in] block_size The size of the blocks - */ + * \brief Set uniform block information + * \param[in] block_size The size of the blocks + */ void setBlockInfos(Arccore::Integer block_size); /*! - * \brief Set uniform block information - * \param[in] blocks The block data - */ + * \brief Set uniform block information + * \param[in] blocks The block data + */ void setBlockInfos(const Block* blocks); /*! - * \brief Set variable block information - * \param[in] blocks The block data - */ + * \brief Set variable block information + * \param[in] blocks The block data + */ void setBlockInfos(const VBlock* blocks); /*! - * \brief Set variable row block information - * \param[in] blocks The row block data - */ + * \brief Set variable row block information + * \param[in] blocks The row block data + */ void setRowBlockInfos(const VBlock* blocks); /*! - * \brief Set variable col block information - * \param[in] blocks The col block data - */ + * \brief Set variable col block information + * \param[in] blocks The col block data + */ void setColBlockInfos(const VBlock* blocks); //! Free resources void free(); + //! Clear resources void clear(); /*! - * \brief Get the row space associated to the matrix - * \returns The row space - */ - const ISpace& rowSpace() const { return *m_row_space.get(); } + * \brief Get the row space associated to the matrix + * \returns The row space + */ + const ISpace& rowSpace() const { return *m_row_space; } /*! - * \brief Get the col space associated to the matrix - * \returns The col space - */ - const ISpace& colSpace() const { return *m_col_space.get(); } + * \brief Get the col space associated to the matrix + * \returns The col space + */ + const ISpace& colSpace() const { return *m_col_space; } /*! - * \brief Get the matrix distribution - * \returns The matrix distribution - */ - const MatrixDistribution& distribution() const { return *m_distribution.get(); } + * \brief Get the matrix distribution + * \returns The matrix distribution + */ + const MatrixDistribution& distribution() const { return *m_distribution; } /*! - * \brief Get uniform block datas - * \returns The matrix block data, or a nullptr if the matrix is scalar or has variable - * blocks - */ + * \brief Get uniform block datas + * \returns The matrix block data, or a nullptr if the matrix is scalar or has variable + * blocks + */ const Block* block() const; /*! - * \brief Get variable block datas - * \returns The matrix block data, or a nullptr if the matrix is scalar or has uniform - * blocks - */ + * \brief Get variable block datas + * \returns The matrix block data, or a nullptr if the matrix is scalar or has uniform + * blocks + */ const VBlock* vblock() const; /*! - * \brief Get variable row block datas - * \returns The matrix row block data, or a nullptr if the matrix is scalar or has - * uniform blocks - */ + * \brief Get variable row block datas + * \returns The matrix row block data, or a nullptr if the matrix is scalar or has + * uniform blocks + */ const VBlock* rowBlock() const; /*! - * \brief Get variable col block datas - * \returns The matrix col block data, or a nullptr if the matrix is scalar or has - * uniform blocks - */ + * \brief Get variable col block datas + * \returns The matrix col block data, or a nullptr if the matrix is scalar or has + * uniform blocks + */ const VBlock* colBlock() const; - public: /*! - * \brief Get a specific matrix implementation - * - * Might induce a conversion, depending on the up to date and requested matrix - * implementation - * - * \returns The up to date matrix in the requested implementation - */ + * \brief Get a specific matrix implementation + * + * Might induce a conversion, depending on the up to date and requested matrix + * implementation + * + * \returns The up to date matrix in the requested implementation + */ template const typename AlgebraTraits::matrix_type& get() const; /*! - * \brief Get a specific matrix implementation - * - * Might induce a conversion, depending on the up to date and requested matrix - * implementation - * - * \param[in] update_stamp Whether or not the timestamp should be increased or not - * \returns The up to date matrix in the requested implementation - */ + * \brief Get a specific matrix implementation + * + * Might induce a conversion, depending on the up to date and requested matrix + * implementation + * + * \param[in] update_stamp Whether or not the timestamp should be increased or not + * \returns The up to date matrix in the requested implementation + */ template - typename AlgebraTraits::matrix_type& get(const bool update_stamp); + typename AlgebraTraits::matrix_type& get(bool update_stamp); //! Release a matrix implementation template void release() const; /*! - * \brief Clone this object - * \return A clone of this object - */ + * \brief Clone this object + * \return A clone of this object + */ MultiMatrixImpl* clone() const; // TOCHECK : should be removed or not ? @@ -214,25 +215,25 @@ class ALIEN_EXPORT MultiMatrixImpl : public TimestampMng private: /*! - * \brief Get a specific matrix implementation - * \param[in] backend The id of the specific implementation - * \returns The matrix in the requested format - */ + * \brief Get a specific matrix implementation + * \param[in] backend The id of the specific implementation + * \returns The matrix in the requested format + */ template IMatrixImpl*& getImpl(BackEndId backend) const; /*! - * \brief Update a matrix implementation - * \param[in] target The targeted implementation - */ + * \brief Update a matrix implementation + * \param[in] target The targeted implementation + */ void updateImpl(IMatrixImpl* target) const; protected: /*! - * \brief Insert a matrix implementation in the multi matrix container - * \param[in] backend The implementation backend id - * \param[in] m The matrix to insert - */ + * \brief Insert a matrix implementation in the multi matrix container + * \param[in] backend The implementation backend id + * \param[in] m The matrix to insert + */ template void insert(BackEndId backend, matrix_type* m); @@ -244,7 +245,7 @@ class ALIEN_EXPORT MultiMatrixImpl : public TimestampMng //! The matrix distribution std::shared_ptr m_distribution; //! The type of the matrix container - typedef std::map MultiMatrixImplMap; + using MultiMatrixImplMap = std::map; //! The matrices container mutable MultiMatrixImplMap m_impls2; //! The uniform block datas @@ -265,7 +266,7 @@ MultiMatrixImpl::get() const // TOCHECK : to be removed or not ? // ALIEN_ASSERT(!m_row_space.isNull(), ("Null row space matrix access")); // ALIEN_ASSERT(!m_col_space.isNull(), ("Null col space matrix access")); - typedef typename AlgebraTraits::matrix_type matrix_type; + using matrix_type = typename AlgebraTraits::matrix_type; IMatrixImpl*& impl2 = getImpl(AlgebraTraits::name()); ALIEN_ASSERT( (impl2->backend() == AlgebraTraits::name()), ("Inconsistent backend")); @@ -283,7 +284,7 @@ MultiMatrixImpl::get(const bool update_stamp) // TOCHECK : to be removed or not ? // ALIEN_ASSERT(!m_row_space.isNull(), ("Null row space matrix access")); // ALIEN_ASSERT(!m_col_space.isNull(), ("Null col space matrix access")); - typedef typename AlgebraTraits::matrix_type matrix_type; + using matrix_type = typename AlgebraTraits::matrix_type; IMatrixImpl*& impl2 = getImpl(AlgebraTraits::name()); ALIEN_ASSERT( (impl2->backend() == AlgebraTraits::name()), ("Inconsistent backend")); @@ -331,7 +332,7 @@ template void MultiMatrixImpl::insert(BackEndId backend, matrix_type* m) { if (m_impls2.find(backend) != m_impls2.end()) { - alien_fatal([&] { cout() << "try to insert already inserted value"; }); + alien_fatal([this] { cout() << "try to insert already inserted value"; }); } m_impls2[backend] = m; } diff --git a/src/core/alien/handlers/scalar/IDirectMatrixBuilder.h b/src/core/alien/handlers/scalar/IDirectMatrixBuilder.h new file mode 100644 index 000000000..4c1718127 --- /dev/null +++ b/src/core/alien/handlers/scalar/IDirectMatrixBuilder.h @@ -0,0 +1,114 @@ +/* + * Copyright 2020 IFPEN-CEA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// -*- C++ -*- +#ifndef ALIEN_COMMON_BUILDER_SCALAR_DIRECTMATRIXBUILDER_H +#define ALIEN_COMMON_BUILDER_SCALAR_DIRECTMATRIXBUILDER_H + +#include + +#include + +#include + +namespace Alien +{ +struct ALIEN_EXPORT DirectMatrixOptions +{ + enum ResetFlag + { + eNoReset, + eResetValues, + eResetProfile, + eResetAllocation + }; + enum ReserveFlag + { + eResetReservation, + eExtendReservation + }; + enum SymmetricFlag + { + eSymmetric, + eUnSymmetric + }; +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +namespace Common +{ + + /*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*/ + + class ALIEN_EXPORT IDirectMatrixBuilder + { + public: + using ReserveFlag = DirectMatrixOptions::ReserveFlag; + + virtual ~IDirectMatrixBuilder() = default; + + virtual void reserve(Arccore::Integer n, ReserveFlag flag) = 0; + + virtual void reserve(Arccore::ConstArrayView indices, Arccore::Integer n, + ReserveFlag flag) = 0; + + virtual void allocate() = 0; + + virtual void addData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) = 0; + + virtual void addData(Arccore::Integer iIndex, Arccore::Real factor, + Arccore::ConstArrayView jIndexes, + Arccore::ConstArrayView jValues) = 0; + + virtual void setData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) = 0; + + virtual void setData(Arccore::Integer iIndex, Arccore::Real factor, + Arccore::ConstArrayView jIndexes, + Arccore::ConstArrayView jValues) = 0; + + virtual void finalize() = 0; + + virtual void squeeze() = 0; + + [[nodiscard]] virtual Arccore::String stats() const = 0; + + [[nodiscard]] virtual Arccore::String stats(Arccore::IntegerConstArrayView ids) const = 0; + + virtual std::optional contribute(Arccore::Integer row, Arccore::Integer col, Arccore::Real value) = 0; + }; + + /*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*/ + + extern ALIEN_EXPORT std::unique_ptr directMatrixBuilderFactory(IMatrix& matrix, DirectMatrixOptions::ResetFlag reset_flag, + DirectMatrixOptions::SymmetricFlag symmetric_flag); + +} // namespace Common + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +} // namespace Alien + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +#endif /* ALIEN_COMMON_BUILDER_SCALAR_DIRECTMATRIXBUILDER_H */ diff --git a/src/core/alien/handlers/scalar/MatrixBuilderFactory.cpp b/src/core/alien/handlers/scalar/MatrixBuilderFactory.cpp new file mode 100644 index 000000000..776e8520f --- /dev/null +++ b/src/core/alien/handlers/scalar/MatrixBuilderFactory.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2023 IFPEN-CEA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// +// Created by chevalierc on 17/05/23. +// + +#include +#include "MatrixBuilderFactory.h" + +namespace Alien::Common +{ + +ALIEN_EXPORT std::unique_ptr directMatrixBuilderFactory(IMatrix& matrix, DirectMatrixOptions::ResetFlag reset_flag, + DirectMatrixOptions::SymmetricFlag symmetric_flag) +{ + return std::make_unique(matrix, reset_flag, symmetric_flag); +} + +MatrixBuilderFactory::MatrixBuilderFactory(BackEndId backend, MatrixBuilderFactory::Factory f) +{ + if (m_default_backend.empty()) { + m_default_backend = backend; + } + m_db.insert({ backend, f }); +} + +std::optional MatrixBuilderFactory::get(BackEndId backend) +{ + if (auto res = m_db.find(backend); res != m_db.end()) { + return std::make_optional(res->second); + } + else { + return std::nullopt; + } +} + +} // namespace Alien::Common +// namespace Alien::Common \ No newline at end of file diff --git a/src/core/alien/handlers/scalar/MatrixBuilderFactory.h b/src/core/alien/handlers/scalar/MatrixBuilderFactory.h new file mode 100644 index 000000000..7d9fce188 --- /dev/null +++ b/src/core/alien/handlers/scalar/MatrixBuilderFactory.h @@ -0,0 +1,76 @@ +/* + * Copyright 2023 IFPEN-CEA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// +// Created by chevalierc on 22/05/23. +// + +#ifndef ALIEN_MATRIXBUILDERFACTORY_H +#define ALIEN_MATRIXBUILDERFACTORY_H + +#include +#include + +#include +#include + +template <> +struct std::hash +{ + std::size_t operator()(Alien::BackEndId const& backend) const noexcept + { + return std::hash{}(backend.localstr()); + } +}; + +namespace Alien +{ +namespace Common + +{ + class ALIEN_EXPORT MatrixBuilderFactory + { + public: + using BackEndId = Alien::BackEndId; + using Factory = std::function(IMatrix&, DirectMatrixOptions::ResetFlag, + DirectMatrixOptions::SymmetricFlag)>; + + MatrixBuilderFactory(BackEndId backend, Factory f); + + MatrixBuilderFactory() {} + + static std::optional get(BackEndId backend); + + static Factory getDefault() + { + return get(m_default_backend).value(); + } + + void setDefault(BackEndId backEndId) + { + m_default_backend = backEndId; + } + + private: + static inline std::unordered_map m_db = {}; + static inline Alien::BackEndId m_default_backend = {}; + }; +} // namespace Common +} // namespace Alien + +#endif //ALIEN_MATRIXBUILDERFACTORY_H diff --git a/src/core/alien/import_export/Reader.h b/src/core/alien/import_export/Reader.h index a6c53bbfe..f004d921c 100644 --- a/src/core/alien/import_export/Reader.h +++ b/src/core/alien/import_export/Reader.h @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include @@ -168,8 +168,8 @@ void loadMMMatrixFromReader(MatrixT& A, ReaderT& reader) DirectMatrixOptions::SymmetricFlag sym_flag = is_symmetric ? DirectMatrixOptions::eSymmetric : DirectMatrixOptions::eUnSymmetric; - Common::DirectMatrixBuilder matrix_builder(A, DirectMatrixOptions::eResetAllocation, sym_flag); - matrix_builder.allocate(); + auto matrix_builder = Common::directMatrixBuilderFactory(A, DirectMatrixOptions::eResetAllocation, sym_flag); + matrix_builder->allocate(); for (int i = 0; i < nnz; ++i) { int li = 0; @@ -183,7 +183,7 @@ void loadMMMatrixFromReader(MatrixT& A, ReaderT& reader) li--; ci--; - matrix_builder.addData(li, ci, val); + matrix_builder->addData(li, ci, val); } } diff --git a/src/core/alien/kernels/dok/BaseDoKDirectMatrixBuilder.cpp b/src/core/alien/kernels/dok/BaseDoKDirectMatrixBuilder.cpp index e875bf3de..7ed521325 100644 --- a/src/core/alien/kernels/dok/BaseDoKDirectMatrixBuilder.cpp +++ b/src/core/alien/kernels/dok/BaseDoKDirectMatrixBuilder.cpp @@ -23,37 +23,64 @@ #include "DoKBackEnd.h" #include "DoKMatrixT.h" +#include "alien/handlers/scalar/MatrixBuilderFactory.h" -namespace Alien +namespace Alien::Common { -Common::BaseDoKDirectMatrixBuilder::BaseDoKDirectMatrixBuilder(Alien::IMatrix& self) +BaseDoKDirectMatrixBuilder::BaseDoKDirectMatrixBuilder(Alien::IMatrix& self, DirectMatrixOptions::ResetFlag reset_flag) : m_matrix(self) { m_matrix.impl()->lock(); + + switch (reset_flag) { + case DirectMatrixOptions::eResetProfile: + case DirectMatrixOptions::eResetAllocation: + m_matrix.impl()->release(); + break; + default: + // Nothing to do + break; + } + m_impl = &m_matrix.impl()->get(true); + + switch (reset_flag) { + case DirectMatrixOptions::eNoReset: + break; + case DirectMatrixOptions::eResetValues: + m_impl->fill(0); + break; + default: + // Nothing to do + break; + } } -Common::BaseDoKDirectMatrixBuilder::~BaseDoKDirectMatrixBuilder() +BaseDoKDirectMatrixBuilder::~BaseDoKDirectMatrixBuilder() { assemble(); } -std::optional Common::BaseDoKDirectMatrixBuilder::contribute(Arccore::Integer row, Arccore::Integer col, Arccore::Real value) +std::optional BaseDoKDirectMatrixBuilder::contribute(Arccore::Integer row, Arccore::Integer col, Arccore::Real value) { - return std::optional(m_impl->addNNZ(row, col, value)); + return { m_impl->addNNZ(row, col, value) }; } -std::optional Common::BaseDoKDirectMatrixBuilder::setNNZ(Arccore::Integer row, Arccore::Integer col, Arccore::Real value) +std::optional BaseDoKDirectMatrixBuilder::setNNZ(Arccore::Integer row, Arccore::Integer col, Arccore::Real value) { m_impl->setNNZ(row, col, value); - return std::optional(value); + return { value }; } -bool Common::BaseDoKDirectMatrixBuilder::assemble() +bool BaseDoKDirectMatrixBuilder::assemble() { m_impl->assemble(); m_matrix.impl()->unlock(); return true; } -} // namespace Alien + +const ALIEN_EXPORT Alien::Common::MatrixBuilderFactory dok_builder_register( +AlgebraTraits::name(), [](IMatrix& matrix, DirectMatrixOptions::ResetFlag reset, [[maybe_unused]] DirectMatrixOptions::SymmetricFlag symmetry) { return std::make_unique(matrix, reset); }); + +} // namespace Alien::Common diff --git a/src/core/alien/kernels/dok/BaseDoKDirectMatrixBuilder.h b/src/core/alien/kernels/dok/BaseDoKDirectMatrixBuilder.h index 6328d9c9b..008ec19ee 100644 --- a/src/core/alien/kernels/dok/BaseDoKDirectMatrixBuilder.h +++ b/src/core/alien/kernels/dok/BaseDoKDirectMatrixBuilder.h @@ -23,6 +23,8 @@ #include +#include + namespace Alien { // Forward declarations. @@ -33,11 +35,11 @@ namespace Common { /*! - * Use DoKMatrix to implement DirectMatrixBuilder. + * Use DoKMatrix to implement IDirectMatrixBuilder. * * This data structure is not compressed like CSR, allowing easy insertion of values. */ - class ALIEN_EXPORT BaseDoKDirectMatrixBuilder + class ALIEN_EXPORT BaseDoKDirectMatrixBuilder : public IDirectMatrixBuilder { public: /*! @@ -45,8 +47,8 @@ namespace Common * @param self the multi-representation handler. It is locked during the life of this object. */ // FIXME: This should be implemented with move-semantic. - explicit BaseDoKDirectMatrixBuilder(IMatrix& self); - ~BaseDoKDirectMatrixBuilder(); + BaseDoKDirectMatrixBuilder(IMatrix& self, DirectMatrixOptions::ResetFlag reset); + ~BaseDoKDirectMatrixBuilder() override; /*! * Add a contribution to a non-zero. Will create the non-zero if needed. @@ -57,7 +59,7 @@ namespace Common * @param value of the contribution * @return a value if insertion is ok */ - std::optional contribute(Integer row, Integer col, Real value); + std::optional contribute(Integer row, Integer col, Real value) override; /*! * Set a value to a non-zero. Will create the non-zero if needed. @@ -78,6 +80,64 @@ namespace Common */ bool assemble(); + void reserve([[maybe_unused]] Arccore::Integer n, [[maybe_unused]] ReserveFlag flag) override + { + // Nothing to do + } + + void reserve([[maybe_unused]] Arccore::ConstArrayView indices, [[maybe_unused]] Arccore::Integer n, [[maybe_unused]] ReserveFlag flag) override + { + // Nothing to do + } + + void allocate() override + { + // Nothing to do + } + + void addData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) override + { + contribute(iIndex, jIndex, value); + } + + void addData(Arccore::Integer iIndex, Arccore::Real factor, Arccore::ConstArrayView jIndexes, Arccore::ConstArrayView jValues) override + { + for (auto offset = 0; offset < jIndexes.length(); offset++) { + contribute(iIndex, jIndexes[offset], jValues[offset] * factor); + } + } + + void setData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) override + { + setNNZ(iIndex, jIndex, value); + } + void setData(Arccore::Integer iIndex, Arccore::Real factor, Arccore::ConstArrayView jIndexes, Arccore::ConstArrayView jValues) override + { + for (auto offset = 0; offset < jIndexes.length(); offset++) { + setNNZ(iIndex, jIndexes[offset], jValues[offset] * factor); + } + } + + void finalize() override + { + assemble(); + } + + void squeeze() override + { + // Nothing to do + } + + String stats() const override + { + return {}; + } + + String stats([[maybe_unused]] Arccore::IntegerConstArrayView ids) const override + { + return {}; + } + private: //! Convenience reference to multi-repr manager. IMatrix& m_matrix; diff --git a/src/core/alien/kernels/dok/DoKLocalMatrixT.h b/src/core/alien/kernels/dok/DoKLocalMatrixT.h index 267f1d0c4..a74e53476 100644 --- a/src/core/alien/kernels/dok/DoKLocalMatrixT.h +++ b/src/core/alien/kernels/dok/DoKLocalMatrixT.h @@ -34,9 +34,6 @@ class DoKLocalMatrixT { public: DoKLocalMatrixT() - : m_indexer(new DoKLocalMatrixIndexer()) - , m_offset(0) - , m_values() {} virtual ~DoKLocalMatrixT() = default; @@ -87,14 +84,14 @@ class DoKLocalMatrixT UniqueArray perm(m_offset); m_r_indexer.reset(m_indexer->sort(perm)); UniqueArray old_vals = m_values; - for (auto curr : perm) { - m_values[curr.second] = old_vals[curr.first]; + for (auto [old_id, new_id] : perm) { + m_values[new_id] = old_vals[old_id]; } } - IReverseIndexer* getReverseIndexer() const { return m_r_indexer.get(); } + [[nodiscard]] IReverseIndexer* getReverseIndexer() const { return m_r_indexer.get(); } - ILocalMatrixIndexer* getIndexer() const { return m_indexer.get(); } + [[nodiscard]] ILocalMatrixIndexer* getIndexer() const { return m_indexer.get(); } ConstArrayView getValues() const { return m_values; } @@ -115,6 +112,11 @@ class DoKLocalMatrixT } } + void fill(Real value) + { + m_values.fill(value); + } + private: void _reallocate(Integer size = 0) { @@ -132,10 +134,9 @@ class DoKLocalMatrixT return offset; } - private: - std::unique_ptr m_indexer; - ILocalMatrixIndexer::Offset m_offset; - UniqueArray m_values; + std::unique_ptr m_indexer = std::make_unique(); + ILocalMatrixIndexer::Offset m_offset = 0; + UniqueArray m_values = {}; std::unique_ptr m_r_indexer; }; diff --git a/src/core/alien/kernels/dok/DoKMatrixT.h b/src/core/alien/kernels/dok/DoKMatrixT.h index 7a3d7ae3c..c15c7d4f7 100644 --- a/src/core/alien/kernels/dok/DoKMatrixT.h +++ b/src/core/alien/kernels/dok/DoKMatrixT.h @@ -38,19 +38,19 @@ namespace Alien class DoKMatrix : public IMatrixImpl { public: - typedef Real ValueType; + using ValueType = Real; - public: explicit DoKMatrix(const MultiMatrixImpl* multi_impl = nullptr) : IMatrixImpl(multi_impl, "DoK") - , m_data() {} DoKMatrix(const DoKMatrix&) = delete; ~DoKMatrix() override = default; - void clear() override {} + void clear() override + { // Nothing to do + } //! Set value of a matrix element, creating it if it does not exist yet. //! \param row id of the row in the matrix @@ -75,6 +75,11 @@ class DoKMatrix : public IMatrixImpl return m_data.add(row, col, value); } + void fill(Real value) + { + m_data.fill(value); + } + //! Dispatch matrix elements void assemble() { _distribute(); } @@ -104,9 +109,8 @@ class DoKMatrix : public IMatrixImpl m_need_update = false; } - private: // TODO remove mutable ! - mutable DoKLocalMatrixT m_data; + mutable DoKLocalMatrixT m_data = {}; bool m_need_update = true; }; diff --git a/src/core/alien/kernels/simple_csr/CMakeLists.txt b/src/core/alien/kernels/simple_csr/CMakeLists.txt index d7f4bfd55..0782f67d7 100644 --- a/src/core/alien/kernels/simple_csr/CMakeLists.txt +++ b/src/core/alien/kernels/simple_csr/CMakeLists.txt @@ -31,6 +31,8 @@ add_library(alien_kernel_simplecsr OBJECT SimpleCSRMatrix.h SimpleCSRVector.cc SimpleCSRVector.h + SimpleCSRDirectMatrixBuilder.cpp + SimpleCSRDirectMatrixBuilder.h redistribution/SimpleCSRDistributorImpl.h redistribution/SimpleCSRDistributorImpl.cc redistribution/SimpleCSRDistributor.h diff --git a/src/core/alien/handlers/scalar/BaseDirectMatrixBuilder.cc b/src/core/alien/kernels/simple_csr/SimpleCSRDirectMatrixBuilder.cpp similarity index 90% rename from src/core/alien/handlers/scalar/BaseDirectMatrixBuilder.cc rename to src/core/alien/kernels/simple_csr/SimpleCSRDirectMatrixBuilder.cpp index 47679f8b3..11a6bfc07 100644 --- a/src/core/alien/handlers/scalar/BaseDirectMatrixBuilder.cc +++ b/src/core/alien/kernels/simple_csr/SimpleCSRDirectMatrixBuilder.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2020 IFPEN-CEA + * Copyright 2023 IFPEN-CEA * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,10 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 */ -#include "BaseDirectMatrixBuilder.h" +// +// Created by chevalierc on 17/05/23. +// + +#include "SimpleCSRDirectMatrixBuilder.h" +#include "alien/handlers/scalar/MatrixBuilderFactory.h" #include #include @@ -62,9 +67,9 @@ namespace Common /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ - DirectMatrixBuilder::DirectMatrixBuilder(IMatrix& matrix, - const DirectMatrixOptions::ResetFlag reset_flag, - const DirectMatrixOptions::SymmetricFlag symmetric_flag) + SimpleCSRDirectMatrixBuilder::SimpleCSRDirectMatrixBuilder(IMatrix& matrix, + const DirectMatrixOptions::ResetFlag reset_flag, + const DirectMatrixOptions::SymmetricFlag symmetric_flag) : m_matrix(matrix) , m_matrix_impl(nullptr) , m_row_starts() @@ -118,7 +123,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - DirectMatrixBuilder::~DirectMatrixBuilder() + SimpleCSRDirectMatrixBuilder::~SimpleCSRDirectMatrixBuilder() { if (!m_finalized) { finalize(); @@ -127,7 +132,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::reserve( + void SimpleCSRDirectMatrixBuilder::reserve( Integer n, const DirectMatrixOptions::ReserveFlag flag) { ALIEN_ASSERT((!m_allocated), ("Cannot reserve already allocated matrix")); @@ -146,7 +151,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::reserve( + void SimpleCSRDirectMatrixBuilder::reserve( const ConstArrayView indices, Integer n, const ReserveFlag flag) { ALIEN_ASSERT((!m_allocated), ("Cannot reserve already allocated matrix")); @@ -166,7 +171,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::allocate() + void SimpleCSRDirectMatrixBuilder::allocate() { _startTimer(); ALIEN_ASSERT((!m_allocated), ("Cannot allocate already allocated matrix")); @@ -231,7 +236,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::addData( + std::optional SimpleCSRDirectMatrixBuilder::contribute( const Integer iIndex, const Integer jIndex, const Real value) { _startTimer(); @@ -239,14 +244,15 @@ namespace Common // skip dead zone if (iIndex == -1 or jIndex == -1) - return; + return std::nullopt; const Integer local_row = iIndex - m_local_offset; -#ifdef CHECKPROFILE_ON_FILLING + if (local_row < 0 or local_row >= m_local_size) - throw FatalErrorException("Cannot add data on undefined row"); -#endif /* CHECKPROFILE_ON_FILLING */ + return std::nullopt; + if (jIndex < -1 or jIndex >= m_col_global_size) - throw FatalErrorException("column index undefined"); + return std::nullopt; + const Integer row_start = m_row_starts[local_row]; Integer& row_size = m_row_sizes[local_row]; Integer row_capacity = m_row_starts[local_row + 1] - row_start; @@ -254,17 +260,21 @@ namespace Common Real* found_value = intrusive_vmap_insert(jIndex, hint_pos, row_size, row_capacity, m_cols.unguardedBasePointer() + row_start, m_values.unguardedBasePointer() + row_start); - if (found_value) - *found_value += value; - else // Manage extra data storage - m_extras[local_row][jIndex] += value; + auto res = value; + if (found_value) { + res = (*found_value += value); + } + else { // Manage extra data storage + res = (m_extras[local_row][jIndex] += value); + } _stopTimer(); + return { res }; } /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::addData(const Integer iIndex, const Real factor, - ConstArrayView jIndexes, ConstArrayView jValues) + void SimpleCSRDirectMatrixBuilder::addData(const Integer iIndex, const Real factor, + ConstArrayView jIndexes, ConstArrayView jValues) { _startTimer(); ALIEN_ASSERT((m_allocated), ("Not allocated matrix")); @@ -307,7 +317,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::setData( + void SimpleCSRDirectMatrixBuilder::setData( const Integer iIndex, const Integer jIndex, const Real value) { _startTimer(); @@ -339,8 +349,8 @@ namespace Common /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::setData(const Integer iIndex, const Real factor, - ConstArrayView jIndexes, ConstArrayView jValues) + void SimpleCSRDirectMatrixBuilder::setData(const Integer iIndex, const Real factor, + ConstArrayView jIndexes, ConstArrayView jValues) { _startTimer(); ALIEN_ASSERT((m_allocated), ("Not allocated matrix")); @@ -383,7 +393,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::finalize() + void SimpleCSRDirectMatrixBuilder::finalize() { if (m_finalized) return; @@ -394,7 +404,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - class DirectMatrixBuilder::IndexEnumerator + class SimpleCSRDirectMatrixBuilder::IndexEnumerator { public: class Finder @@ -435,7 +445,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - class DirectMatrixBuilder::FullEnumerator + class SimpleCSRDirectMatrixBuilder::FullEnumerator { public: class Finder @@ -468,7 +478,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - String DirectMatrixBuilder::stats() const + String SimpleCSRDirectMatrixBuilder::stats() const { std::ostringstream oss; _stats(oss, FullEnumerator(m_local_size)); @@ -477,7 +487,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - String DirectMatrixBuilder::stats(ConstArrayView ids) const + String SimpleCSRDirectMatrixBuilder::stats(ConstArrayView ids) const { std::ostringstream oss; _stats(oss, IndexEnumerator(ids, m_local_offset)); @@ -486,7 +496,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::squeeze() + void SimpleCSRDirectMatrixBuilder::squeeze() { bool need_squeeze = false; @@ -582,7 +592,7 @@ namespace Common /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::computeProfile(const ConstArrayView sizes) + void SimpleCSRDirectMatrixBuilder::computeProfile(const ConstArrayView sizes) { UniqueArray m_offset; m_offset.resize(m_nproc + 1); @@ -621,8 +631,8 @@ namespace Common /*---------------------------------------------------------------------------*/ - void DirectMatrixBuilder::updateProfile(UniqueArray& row_starts, - UniqueArray& cols, UniqueArray& values) + void SimpleCSRDirectMatrixBuilder::updateProfile(UniqueArray& row_starts, + UniqueArray& cols, UniqueArray& values) { SimpleCSRInternal::CSRStructInfo& profile = m_matrix_impl->internal().getCSRProfile(); profile.getRowOffset().copy(row_starts); @@ -653,7 +663,7 @@ namespace Common /*---------------------------------------------------------------------------*/ template - void DirectMatrixBuilder::_stats(std::ostream& o, const Enumerator& e) const + void SimpleCSRDirectMatrixBuilder::_stats(std::ostream& o, const Enumerator& e) const { bool need_squeeze = false; Integer total_used_data = 0; @@ -720,6 +730,9 @@ namespace Common << "Need squeeze optimization = " << std::boolalpha << need_squeeze << "\n"; } + const ALIEN_EXPORT Alien::Common::MatrixBuilderFactory simplecsr_builder_register( + AlgebraTraits::name(), [](IMatrix& matrix, DirectMatrixOptions::ResetFlag reset, DirectMatrixOptions::SymmetricFlag symmetry) { return std::make_unique(matrix, reset, symmetry); }); + /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ diff --git a/src/core/alien/handlers/scalar/BaseDirectMatrixBuilder.h b/src/core/alien/kernels/simple_csr/SimpleCSRDirectMatrixBuilder.h similarity index 69% rename from src/core/alien/handlers/scalar/BaseDirectMatrixBuilder.h rename to src/core/alien/kernels/simple_csr/SimpleCSRDirectMatrixBuilder.h index 04f36f601..8186b5a4b 100644 --- a/src/core/alien/handlers/scalar/BaseDirectMatrixBuilder.h +++ b/src/core/alien/kernels/simple_csr/SimpleCSRDirectMatrixBuilder.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 IFPEN-CEA + * Copyright 2023 IFPEN-CEA * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 */ -// -*- C++ -*- -#ifndef ALIEN_COMMON_BUILDER_SCALAR_DIRECTMATRIXBUILDER_H -#define ALIEN_COMMON_BUILDER_SCALAR_DIRECTMATRIXBUILDER_H -/* Author : havep at Tue Aug 28 13:56:24 2012 - * Generated by createNew - */ +// +// Created by chevalierc on 17/05/23. +// + +#ifndef ALIEN_SIMPLECSRDIRECTBUILDER_H +#define ALIEN_SIMPLECSRDIRECTBUILDER_H #include @@ -31,7 +31,10 @@ #define USE_VMAP #ifdef USE_VMAP + #include +#include + #endif /* USE_VMAP */ namespace Arccore @@ -58,37 +61,13 @@ class SimpleCSRMatrix; /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -struct DirectMatrixOptions -{ - enum ResetFlag - { - eNoReset, - eResetValues, - eResetProfile, - eResetAllocation - }; - enum ReserveFlag - { - eResetReservation, - eExtendReservation - }; - enum SymmetricFlag - { - eSymmetric, - eUnSymmetric - }; -}; - -/*---------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ - namespace Common { /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ - class ALIEN_EXPORT DirectMatrixBuilder + class ALIEN_EXPORT SimpleCSRDirectMatrixBuilder : public IDirectMatrixBuilder { public: using ResetFlag = DirectMatrixOptions::ResetFlag; @@ -96,69 +75,83 @@ namespace Common using SymmetricFlag = DirectMatrixOptions::SymmetricFlag; public: - using MatrixElement = MatrixElementT; + using MatrixElement = MatrixElementT; public: - DirectMatrixBuilder(IMatrix& matrix, ResetFlag reset_flag, - SymmetricFlag symmetric_flag = SymmetricFlag::eSymmetric); + SimpleCSRDirectMatrixBuilder(IMatrix& matrix, ResetFlag reset_flag, + SymmetricFlag symmetric_flag = SymmetricFlag::eSymmetric); - virtual ~DirectMatrixBuilder(); + ~SimpleCSRDirectMatrixBuilder() override; - DirectMatrixBuilder(DirectMatrixBuilder&) = delete; - DirectMatrixBuilder(DirectMatrixBuilder&&) = delete; - DirectMatrixBuilder& operator=(const DirectMatrixBuilder&) = delete; - DirectMatrixBuilder& operator=(DirectMatrixBuilder&&) = delete; + SimpleCSRDirectMatrixBuilder(SimpleCSRDirectMatrixBuilder&) = delete; + + SimpleCSRDirectMatrixBuilder(SimpleCSRDirectMatrixBuilder&&) = delete; + + SimpleCSRDirectMatrixBuilder& operator=(const SimpleCSRDirectMatrixBuilder&) = delete; + + SimpleCSRDirectMatrixBuilder& operator=(SimpleCSRDirectMatrixBuilder&&) = delete; - public: MatrixElement operator()(const Integer iIndex, const Integer jIndex) { return MatrixElement(iIndex, jIndex, *this); } - void reserve(Arccore::Integer n, ReserveFlag flag = ReserveFlag::eResetReservation); + void reserve(Arccore::Integer n, ReserveFlag flag = ReserveFlag::eResetReservation) override; void reserve(Arccore::ConstArrayView indices, Arccore::Integer n, - ReserveFlag flag = ReserveFlag::eResetReservation); + ReserveFlag flag = ReserveFlag::eResetReservation) override; - void allocate(); + void allocate() override; - void addData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value); + void addData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) override + { + if (!contribute(iIndex, jIndex, value).has_value()) { +#ifdef CHECKPROFILE_ON_FILLING + hrow FatalErrorException(std::format("Cannot add ({}, {})", iIndex, jIndex); +#endif + } + } void addData(Arccore::Integer iIndex, Arccore::Real factor, Arccore::ConstArrayView jIndexes, - Arccore::ConstArrayView jValues); + Arccore::ConstArrayView jValues) override; - void setData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value); + void setData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) override; void setData(Arccore::Integer iIndex, Arccore::Real factor, Arccore::ConstArrayView jIndexes, - Arccore::ConstArrayView jValues); + Arccore::ConstArrayView jValues) override; - void finalize(); + void finalize() override; - void squeeze(); + void squeeze() override; - [[nodiscard]] Arccore::String stats() const; - [[nodiscard]] Arccore::String stats(Arccore::IntegerConstArrayView ids) const; + [[nodiscard]] Arccore::String stats() const override; + + [[nodiscard]] Arccore::String stats(Arccore::IntegerConstArrayView ids) const override; + + std::optional contribute(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) override; protected: IMatrix& m_matrix; SimpleCSRMatrix* m_matrix_impl; - Integer m_local_offset, m_global_size, m_local_size; - Integer m_col_global_size; + Integer m_local_offset = 0; + Integer m_global_size = 0; + Integer m_local_size = 0; + Integer m_col_global_size = 0; ArrayView m_row_starts; ArrayView m_cols; ArrayView m_values; UniqueArray m_row_sizes; - ResetFlag m_reset_flag; - bool m_allocated; - bool m_finalized; - bool m_symmetric_profile; + ResetFlag m_reset_flag = DirectMatrixOptions::ResetFlag::eNoReset; + bool m_allocated = false; + bool m_finalized = false; + bool m_symmetric_profile = false; - Integer m_nproc; + Integer m_nproc = 0; IMessagePassingMng* m_parallel_mng; ITraceMng* m_trace; @@ -172,17 +165,20 @@ namespace Common private: void computeProfile(Arccore::ConstArrayView sizes); + void updateProfile(Arccore::UniqueArray& row_starts, Arccore::UniqueArray& cols, Arccore::UniqueArray& values); class IndexEnumerator; + class FullEnumerator; template void _stats(std::ostream& o, const Enumerator& e) const; void _startTimer() {} + void _stopTimer() {} }; @@ -198,5 +194,4 @@ namespace Common /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ - -#endif /* ALIEN_COMMON_BUILDER_SCALAR_DIRECTMATRIXBUILDER_H */ +#endif //ALIEN_SIMPLECSRDIRECTBUILDER_H diff --git a/src/movesemantic/CMakeLists.txt b/src/movesemantic/CMakeLists.txt index e40639876..1904e578d 100644 --- a/src/movesemantic/CMakeLists.txt +++ b/src/movesemantic/CMakeLists.txt @@ -28,7 +28,6 @@ set(alien_semantic_public_header alien/move/handlers/sub_matrix/Extraction.h alien/move/data/MatrixData.h alien/move/data/VectorData.h - alien/move/handlers/scalar/DoKDirectMatrixBuilder.h alien/move/data/Redistribution.h) add_library(alien_semantic_move @@ -38,7 +37,7 @@ add_library(alien_semantic_move alien/move/data/VectorData.cc alien/move/impl/MatrixMarketReader.cc alien/move/data/Redistribution.cpp - ) +) if (ALIEN_GENERATE_DOCUMENTATION) set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") @@ -46,7 +45,7 @@ if (ALIEN_GENERATE_DOCUMENTATION) ${alien_semantic_public_header} USE_STAMP_FILE COMMENT "Generate API-documents for Alien." - ) + ) endif (ALIEN_GENERATE_DOCUMENTATION) target_link_libraries(alien_semantic_move PUBLIC alien_core) @@ -61,7 +60,7 @@ generate_export_header(alien_semantic_move EXPORT_MACRO_NAME ALIEN_MOVESEMANTIC_EXPORT EXPORT_FILE_NAME alien/move/AlienMoveSemanticExport.h STATIC_DEFINE ${PROJECT_NAME}_BUILT_AS_STATIC - ) +) install(TARGETS alien_semantic_move EXPORT ${ALIEN_EXPORT_TARGET} @@ -75,7 +74,7 @@ enable_sanitizers(alien_semantic_move) install(DIRECTORY alien/move DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/alien FILES_MATCHING PATTERN "*.h" - ) +) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/alien/move/AlienMoveSemanticExport.h diff --git a/src/movesemantic/alien/move/handlers/scalar/DirectMatrixBuilder.h b/src/movesemantic/alien/move/handlers/scalar/DirectMatrixBuilder.h index bc1952153..ed1aed69d 100644 --- a/src/movesemantic/alien/move/handlers/scalar/DirectMatrixBuilder.h +++ b/src/movesemantic/alien/move/handlers/scalar/DirectMatrixBuilder.h @@ -18,10 +18,12 @@ #pragma once -#include +#include +#include #include #include +#include /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -32,28 +34,112 @@ namespace Alien::Move /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -class DirectMatrixBuilder : protected MoveObject -, public Common::DirectMatrixBuilder +class ALIEN_MOVESEMANTIC_EXPORT DirectMatrixBuilder { public: - using Common::DirectMatrixBuilder::ReserveFlag; - using Common::DirectMatrixBuilder::ResetFlag; - using Common::DirectMatrixBuilder::SymmetricFlag; + using ResetFlag = DirectMatrixOptions::ResetFlag; + using ReserveFlag = DirectMatrixOptions::ReserveFlag; + using SymmetricFlag = DirectMatrixOptions::SymmetricFlag; + + using MatrixElement = MatrixElementT; DirectMatrixBuilder(MatrixData&& matrix, const ResetFlag reset_flag, - const SymmetricFlag symmetric_flag = SymmetricFlag::eSymmetric) - : MoveObject(std::move(matrix)) - , Common::DirectMatrixBuilder(reference(), reset_flag, symmetric_flag) - {} + const SymmetricFlag symmetric_flag = SymmetricFlag::eSymmetric, std::optional backend = std::nullopt) + : m_data(std::move(matrix)) + { + auto factory = Common::MatrixBuilderFactory::getDefault(); + if (backend.has_value()) { + factory = Common::MatrixBuilderFactory::get(backend.value()).value_or(factory); + } + m_builder = factory(m_data, reset_flag, symmetric_flag); + } + + MatrixElement operator()(const Integer iIndex, const Integer jIndex) + { + return MatrixElement(iIndex, jIndex, *this); + } + + void reserve(Arccore::Integer n, + ReserveFlag flag = ReserveFlag::eResetReservation) + { + m_builder->reserve(n, flag); + } + + void reserve(Arccore::ConstArrayView indices, Arccore::Integer n, + ReserveFlag flag = ReserveFlag::eResetReservation) + { + m_builder->reserve(indices, n, flag); + } + + void allocate() + { + m_builder->allocate(); + } - virtual ~DirectMatrixBuilder() = default; + void addData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) + { + m_builder->addData(iIndex, jIndex, value); + } + + void addData(Arccore::Integer iIndex, Arccore::Real factor, + Arccore::ConstArrayView jIndexes, + Arccore::ConstArrayView jValues) + { + m_builder->addData(iIndex, factor, jIndexes, jValues); + } + + void setData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) + { + m_builder->setData(iIndex, jIndex, value); + } + + void setData(Arccore::Integer iIndex, Arccore::Real factor, + Arccore::ConstArrayView jIndexes, + Arccore::ConstArrayView jValues) + { + m_builder->setData(iIndex, factor, jIndexes, jValues); + } + + void finalize() + { + m_builder->finalize(); + } + + void squeeze() + { + m_builder->squeeze(); + } + + [[nodiscard]] Arccore::String stats() const + { + return m_builder->stats(); + } + + [[nodiscard]] Arccore::String stats(Arccore::IntegerConstArrayView ids) const + { + return m_builder->stats(ids); + } MatrixData&& release() { - finalize(); + m_builder->finalize(); + m_builder.reset(nullptr); - return MoveObject::release(); + return std::move(m_data); } + + std::optional contribute(Arccore::Integer row, Arccore::Integer col, Arccore::Real value) + { + if (!m_builder) { + return std::nullopt; + } + + return m_builder->contribute(row, col, value); + } + + private: + MatrixData m_data; + std::unique_ptr m_builder; }; /*---------------------------------------------------------------------------*/ diff --git a/src/movesemantic/alien/move/handlers/scalar/DoKDirectMatrixBuilder.h b/src/movesemantic/alien/move/handlers/scalar/DoKDirectMatrixBuilder.h deleted file mode 100644 index 6ae693a5d..000000000 --- a/src/movesemantic/alien/move/handlers/scalar/DoKDirectMatrixBuilder.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2021 IFPEN-CEA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ALIEN_DOKDIRECTMATRIXBUILDER_H -#define ALIEN_DOKDIRECTMATRIXBUILDER_H - -#include - -#include -#include - -#include - -#include - -namespace Alien::Move -{ -class ALIEN_MOVESEMANTIC_EXPORT DoKDirectMatrixBuilder -{ - public: - explicit DoKDirectMatrixBuilder(MatrixData&& self) - : m_data(std::move(self)) - { - m_builder = std::make_unique(Alien::Common::BaseDoKDirectMatrixBuilder(m_data)); - } - virtual ~DoKDirectMatrixBuilder() = default; - - DoKDirectMatrixBuilder(const DoKDirectMatrixBuilder&) = delete; - DoKDirectMatrixBuilder& operator=(const DoKDirectMatrixBuilder&) = delete; - DoKDirectMatrixBuilder(DoKDirectMatrixBuilder&&) = delete; - DoKDirectMatrixBuilder& operator=(DoKDirectMatrixBuilder&&) = delete; - - std::optional contribute(Arccore::Integer row, Arccore::Integer col, Arccore::Real value) - { - if (!m_builder) { - return std::nullopt; - } - - return m_builder->contribute(row, col, value); - } - - MatrixData&& release() - { - m_builder->assemble(); - m_builder.reset(nullptr); - return std::move(m_data); - } - - private: - MatrixData m_data; - std::unique_ptr m_builder; -}; -} // namespace Alien::Move -#endif //ALIEN_DOKDIRECTMATRIXBUILDER_H diff --git a/src/movesemantic/alien/move/impl/MatrixMarketReader.cc b/src/movesemantic/alien/move/impl/MatrixMarketReader.cc index 021da92a8..7abc37d51 100644 --- a/src/movesemantic/alien/move/impl/MatrixMarketReader.cc +++ b/src/movesemantic/alien/move/impl/MatrixMarketReader.cc @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include #include @@ -133,7 +133,7 @@ namespace return std::make_optional(out); } - bool readValues(std::istream& fstream, DoKDirectMatrixBuilder& builder, bool symmetric, size_t start, size_t stop) + bool readValues(std::istream& fstream, DirectMatrixBuilder& builder, bool symmetric, size_t start, size_t stop) { for (size_t i = 0; i < start; ++i) { fstream.ignore(4096, '\n'); @@ -186,7 +186,7 @@ readFromMatrixMarket(Arccore::MessagePassing::IMessagePassingMng* pm, const std: if (!desc) { throw Arccore::FatalErrorException("readFromMatrixMarket", "Invalid header"); } - DoKDirectMatrixBuilder builder(createMatrixData(desc.value(), pm)); + DirectMatrixBuilder builder(createMatrixData(desc.value(), pm), Alien::DirectMatrixOptions::eResetValues, Alien::DirectMatrixOptions::eSymmetric, std::make_optional(Alien::AlgebraTraits::name())); auto [nnz_start, nnz_stop] = partition(desc.value().n_nnz, pm); readValues(stream, builder, desc->symmetric, nnz_start, nnz_stop); diff --git a/src/movesemantic/tests/TestDoKDirectMatrixBuilder.cc b/src/movesemantic/tests/TestDoKDirectMatrixBuilder.cc index bec0b4828..123a3d704 100644 --- a/src/movesemantic/tests/TestDoKDirectMatrixBuilder.cc +++ b/src/movesemantic/tests/TestDoKDirectMatrixBuilder.cc @@ -23,9 +23,8 @@ #include #include -#include -#include -#include +#include +#include #include #include @@ -42,7 +41,7 @@ TEST(TestDoKDirectMatrixBuilder, Fill) ASSERT_EQ(A.rowSpace(), row_space); ASSERT_EQ(A.colSpace(), col_space); { - auto builder = Alien::Move::DoKDirectMatrixBuilder(std::move(A)); + Alien::Move::DirectMatrixBuilder builder(std::move(A), Alien::DirectMatrixOptions::eResetValues, Alien::DirectMatrixOptions::eSymmetric, std::make_optional(Alien::AlgebraTraits::name())); // With DokDirectMatrixBuilder, this code is valid for all ranks. // We can fill non-local non-zeros. diff --git a/src/refsemantic/alien/ref/handlers/scalar/DirectMatrixBuilder.h b/src/refsemantic/alien/ref/handlers/scalar/DirectMatrixBuilder.h index 0db4da3f4..f27f6ee11 100644 --- a/src/refsemantic/alien/ref/handlers/scalar/DirectMatrixBuilder.h +++ b/src/refsemantic/alien/ref/handlers/scalar/DirectMatrixBuilder.h @@ -18,9 +18,10 @@ #pragma once -#include +#include #include +#include /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -31,17 +32,89 @@ namespace Alien /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -class DirectMatrixBuilder : public Common::DirectMatrixBuilder +class DirectMatrixBuilder { public: - using Common::DirectMatrixBuilder::ReserveFlag; - using Common::DirectMatrixBuilder::ResetFlag; - using Common::DirectMatrixBuilder::SymmetricFlag; + using ResetFlag = DirectMatrixOptions::ResetFlag; + using ReserveFlag = DirectMatrixOptions::ReserveFlag; + using SymmetricFlag = DirectMatrixOptions::SymmetricFlag; + + using MatrixElement = MatrixElementT; DirectMatrixBuilder(Matrix& matrix, const ResetFlag reset_flag, const SymmetricFlag symmetric_flag = SymmetricFlag::eSymmetric) - : Common::DirectMatrixBuilder(matrix, reset_flag, symmetric_flag) - {} + { + m_builder = Common::directMatrixBuilderFactory(matrix, reset_flag, symmetric_flag); + } + + MatrixElement operator()(const Integer iIndex, const Integer jIndex) + { + return MatrixElement(iIndex, jIndex, *m_builder.get()); + } + + void reserve(Arccore::Integer n, + ReserveFlag flag = ReserveFlag::eResetReservation) + { + m_builder->reserve(n, flag); + } + + void reserve(Arccore::ConstArrayView indices, Arccore::Integer n, + ReserveFlag flag = ReserveFlag::eResetReservation) + { + m_builder->reserve(indices, n, flag); + } + + void allocate() + { + m_builder->allocate(); + } + + void addData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) + { + m_builder->addData(iIndex, jIndex, value); + } + + void addData(Arccore::Integer iIndex, Arccore::Real factor, + Arccore::ConstArrayView jIndexes, + Arccore::ConstArrayView jValues) + { + m_builder->addData(iIndex, factor, jIndexes, jValues); + } + + void setData(Arccore::Integer iIndex, Arccore::Integer jIndex, Arccore::Real value) + { + m_builder->setData(iIndex, jIndex, value); + } + + void setData(Arccore::Integer iIndex, Arccore::Real factor, + Arccore::ConstArrayView jIndexes, + Arccore::ConstArrayView jValues) + { + m_builder->setData(iIndex, factor, jIndexes, jValues); + } + + void finalize() + { + m_builder->finalize(); + } + + void squeeze() + { + m_builder->squeeze(); + } + + [[nodiscard]] Arccore::String stats() const + { + return m_builder->stats(); + } + + [[nodiscard]] Arccore::String stats(Arccore::IntegerConstArrayView ids) const + { + return m_builder->stats(ids); + } + + private: + std::unique_ptr m_builder; }; /*---------------------------------------------------------------------------*/