Skip to content

Commit

Permalink
Merge branch 'stack/ogl_0.6' into impl/repartitioner_sparsity
Browse files Browse the repository at this point in the history
  • Loading branch information
greole authored Sep 27, 2024
2 parents 45c5f7f + 28cd0f8 commit 88a9c83
Show file tree
Hide file tree
Showing 22 changed files with 1,389 additions and 169 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ target_sources(
src/DevicePersistent/ExecutorHandler/ExecutorHandler.C
src/MatrixWrapper/HostMatrix.C
src/MatrixWrapper/SparsityPattern.C
src/MatrixWrapper/Distributed.C
src/Repartitioner.C
# src/Solver/CG/GKOCG.C src/Solver/BiCGStab/GKOBiCGStab.C
# src/Solver/GMRES/GKOGMRES.C
Expand Down
1 change: 1 addition & 0 deletions cmake/ginkgo.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ include(FetchContent)
if(NOT ${OGL_USE_EXTERNAL_GINKGO})
FetchContent_Declare(
Ginkgo
SYSTEM
QUITE
GIT_SHALLOW ON
GIT_REPOSITORY "https://github.com/ginkgo-project/ginkgo.git"
Expand Down
6 changes: 6 additions & 0 deletions include/OGL/CommunicationPattern.H
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ struct CommunicationPattern {
*/
gko::array<label> total_rank_send_idx() const;

/* @brief concatenate all separate send idxs arrays into one contiguous
* array
*/
gko::array<label> compute_recv_gather_idxs(
const ExecutorHandler &exec_handler) const;


/** Computes the send and recv pattern for ginkgos distributed matrix SpMV
*/
Expand Down
5 changes: 2 additions & 3 deletions include/OGL/DevicePersistent/DeviceIdGuard.H
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ struct DeviceIdGuardInitFunctor {
std::shared_ptr<gko::scoped_device_id_guard> init() const
{
return std::make_shared<gko::scoped_device_id_guard>(
std::move(executor_->get_scoped_device_id_guard()));
executor_->get_scoped_device_id_guard());
// std::move(executor_->get_scoped_device_id_guard()));
}
};

Expand All @@ -41,6 +42,4 @@ public:
{}
};


} // namespace Foam
// namespace Foam
21 changes: 11 additions & 10 deletions include/OGL/DevicePersistent/Partition.H
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,18 @@ struct PartitionInitFunctor {

std::shared_ptr<part_type> init() const
{
auto exec = exec_.get_ref_exec();
auto comm = exec_.get_gko_mpi_host_comm();
FatalErrorInFunction << "Not implemented" << abort(FatalError);
// auto exec = exec_.get_ref_exec();
// auto comm = exec_.get_gko_mpi_host_comm();

word msg{"initialising partition of size " +
std::to_string(local_size_)};
LOG_1(verbose_, msg)
// word msg{"initialising partition of size " +
// std::to_string(local_size_)};
// LOG_1(verbose_, msg)

if (ranks_per_gpu_ == 1) return {};
// if (ranks_per_gpu_ == 1) return {};


return {};
}
};

Expand All @@ -84,8 +88,6 @@ class PersistentPartition

mutable label global_elements_;

const ExecutorHandler &exec_;

public:
using part_type = gko::experimental::distributed::Partition<label, label>;
/* PersistentPartition constructor using existing memory
Expand All @@ -107,8 +109,7 @@ public:
communication_pattern),
false, verbose),
ranks_per_gpu_(ranks_per_gpu),
local_elements_(elements),
exec_(exec)
local_elements_(elements)
{
auto comm = exec.get_gko_mpi_host_comm();
label local_elements = local_elements_;
Expand Down
60 changes: 57 additions & 3 deletions include/OGL/MatrixWrapper/Combination.H
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "fvCFD.H"


/* @brief The CombinationMatrix class is a wrapper around Ginkgos combination
* linear operator. It provides an interface for creating linear combinations of
* a given inner matrix type and a read implementation
Expand All @@ -18,7 +19,8 @@ class CombinationMatrix
public gko::EnableCreateMethod<CombinationMatrix<InnerMatrixType>>,
public gko::ReadableFromMatrixData<scalar, label>,
public gko::ConvertibleTo<gko::matrix::Coo<scalar, label>>,
public gko::ConvertibleTo<gko::matrix::Csr<scalar, label>> {
public gko::ConvertibleTo<gko::matrix::Csr<scalar, label>>,
public gko::WritableToMatrixData<scalar, label> {
friend class gko::EnableCreateMethod<CombinationMatrix<InnerMatrixType>>;
friend class gko::EnablePolymorphicObject<
CombinationMatrix<InnerMatrixType>, gko::LinOp>;
Expand Down Expand Up @@ -66,6 +68,25 @@ public:
return *this;
}


void write(gko::matrix_data<scalar> &res) const override
{
auto exec = this->get_executor();
auto operators = this->get_operators();

std::vector<gko::matrix_data_entry<scalar, label>> data;
for (auto op : operators) {
auto tmp_mat_data = gko::matrix_data<scalar>();
gko::as<InnerMatrixType>(op)->write(tmp_mat_data);
data.insert(data.end(), tmp_mat_data.nonzeros.begin(),
tmp_mat_data.nonzeros.end());
}
auto mat_data = gko::matrix_data<scalar>();
res.nonzeros = data;
res.size = this->get_size();
}


/**
* Returns a list of coefficients of the combination.
*
Expand Down Expand Up @@ -176,7 +197,7 @@ protected:
* */
void apply_impl(const gko::LinOp *b, gko::LinOp *x) const override
{
if (this->get_size()[0] > 0) {
if (this->get_size()[0] > 0 && this->get_size()[1] > 0) {
this->comb_->apply(b, x);
}
}
Expand All @@ -187,11 +208,44 @@ protected:
void apply_impl(const gko::LinOp *alpha, const gko::LinOp *b,
const gko::LinOp *beta, gko::LinOp *x) const override
{
if (this->get_size()[0] > 0) {
if (this->get_size()[0] > 0 && this->get_size()[1] > 0) {
this->comb_->apply(alpha, b, beta, x);
}
}

private:
std::shared_ptr<gko::Combination<scalar>> comb_;
};


namespace detail {
std::shared_ptr<gko::matrix::Coo<scalar, label>> convert_combination_to_coo(
std::shared_ptr<const gko::Executor> exec,
std::shared_ptr<const gko::LinOp> in)
{
auto out = gko::share(gko::matrix::Coo<scalar, label>::create(exec));
gko::as<CombinationMatrix<gko::matrix::Coo<scalar, label>>>(in)->convert_to(
out.get());

return out;
}

template <typename InnerMatrixType>
void export_mtx(const word fieldName,
std::shared_ptr<CombinationMatrix<InnerMatrixType>> out,
const word local, const objectRegistry &db,
const word matrixFormat)
{
std::string folder{db.time().timePath()};
std::filesystem::create_directories(folder);
std::string fn{folder + "/" + fieldName + "_A_" + local + ".mtx"};
std::cout << "exporting " << fn << std::endl;
std::ofstream stream{fn};
stream << std::setprecision(15);

auto coo = gko::share(
gko::matrix::Coo<scalar, label>::create(out->get_executor()));
out->convert_to(coo);
}

} // namespace detail
192 changes: 192 additions & 0 deletions include/OGL/MatrixWrapper/Distributed.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// SPDX-FileCopyrightText: 2024 OGL authors
//
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include <map>

#include <ginkgo/core/distributed/lin_op.hpp>
#include <ginkgo/ginkgo.hpp>

#include "OGL/CommunicationPattern.H"
#include "OGL/MatrixWrapper/Combination.H"
#include "OGL/MatrixWrapper/HostMatrix.H"
#include "OGL/Repartitioner.H"


/* The RepartDistMatrix class is a wrapper around Ginkgos distributed Matrix
* class
*
* It adds functionality for repeated read and repartitioning operatitions. As a
* constraint it is required that the inner matrix types of the distributed
* matrix are of RepartDistMatrix type.
* */
template <typename LocalMatrixType>
class RepartDistMatrix
: public gko::experimental::EnableDistributedLinOp<
RepartDistMatrix<LocalMatrixType>>,
public gko::EnableCreateMethod<RepartDistMatrix<LocalMatrixType>>,
public gko::experimental::distributed::DistributedBase {
friend class gko::EnableCreateMethod<RepartDistMatrix<LocalMatrixType>>;
friend class gko::EnablePolymorphicObject<RepartDistMatrix<LocalMatrixType>,
gko::LinOp>;

using dist_mtx =
gko::experimental::distributed::Matrix<scalar, label, label>;

using part_type = gko::experimental::distributed::Partition<label, label>;

using vec = gko::matrix::Dense<scalar>;
using device_matrix_data = gko::device_matrix_data<scalar, label>;
using communicator = gko::experimental::mpi::communicator;

public:
using gko::experimental::EnableDistributedLinOp<
RepartDistMatrix<LocalMatrixType>>::convert_to;
using gko::experimental::EnableDistributedLinOp<
RepartDistMatrix<LocalMatrixType>>::move_to;

std::shared_ptr<const gko::LinOp> get_local_matrix()
{
return this->dist_mtx_->get_local_matrix();
}

std::shared_ptr<const gko::LinOp> get_non_local_matrix()
{
return this->dist_mtx_->get_non_local_matrix();
}

/**
* Copy-assigns a CombinationMatrix matrix. Preserves executor, copies
* everything else.
*/
RepartDistMatrix &operator=(const RepartDistMatrix &other)
{
if (&other != this) {
// FatalErrorInFunction << "Copying the RepartDistMatrix is
// disallowed "
// "for performance reasons"
// << abort(FatalError);
gko::experimental::EnableDistributedLinOp<
RepartDistMatrix>::operator=(other);
this->dist_mtx_ = other.dist_mtx_;
this->local_sparsity_ = other.local_sparsity_;
this->non_local_sparsity_ = other.non_local_sparsity_;
this->src_comm_pattern_ = other.src_comm_pattern_;
this->local_interfaces_ = other.local_interfaces_;
}
return *this;
}

/**
* Move-assigns a CombinationMatrix matrix. Preserves executor, moves the
* data and leaves the moved-from object in an empty state (0x0 LinOp with
* unchanged executor and strategy, no nonzeros and valid row pointers).
*/
RepartDistMatrix &operator=(RepartDistMatrix &&other)
{
if (&other != this) {
FatalErrorInFunction << "Not implemented" << abort(FatalError);
gko::experimental::EnableDistributedLinOp<
RepartDistMatrix>::operator=(std::move(other));
this->dist_mtx_ = std::move(other.dist_mtx_);
this->local_sparsity_ = std::move(other.local_sparsity_);
this->non_local_sparsity_ = std::move(other.non_local_sparsity_);
this->src_comm_pattern_ = std::move(other.src_comm_pattern_);
this->local_interfaces_ = std::move(other.local_interfaces_);
}
return *this;
}

static std::shared_ptr<gko::LinOp> create(
const ExecutorHandler &exec_handler, const Repartitioner &repartitioner,
std::shared_ptr<const HostMatrixWrapper> host_A);

void update(const ExecutorHandler &exec_handler,
const Repartitioner &repartitioner,
std::shared_ptr<const HostMatrixWrapper> host_A);

RepartDistMatrix(
std::shared_ptr<const gko::Executor> exec, communicator comm,
gko::dim<2> local_size, gko::dim<2> global_size,
std::shared_ptr<dist_mtx> dist_mtx,
std::shared_ptr<const SparsityPattern> local_sparsity,
std::shared_ptr<const SparsityPattern> non_local_sparsity,
std::shared_ptr<const CommunicationPattern> src_comm_pattern,
std::vector<std::pair<bool, label>> &local_interfaces)
: gko::experimental::EnableDistributedLinOp<RepartDistMatrix>(exec),
gko::experimental::distributed::DistributedBase(comm),
dist_mtx_(std::move(dist_mtx)),
local_sparsity_(local_sparsity),
non_local_sparsity_(non_local_sparsity),
src_comm_pattern_(src_comm_pattern),
local_interfaces_(local_interfaces)
{
this->set_size(global_size);
}

void write(const word field_name_, const objectRegistry &db_) const;

// Needed for distributed/polymorphic_object.hpp
RepartDistMatrix(std::shared_ptr<const gko::Executor> exec,
communicator comm)
: gko::experimental::EnableDistributedLinOp<RepartDistMatrix>(exec),
gko::experimental::distributed::DistributedBase{comm}
{}

protected:
// Here we implement the application of the linear operator, x = A * b.
// apply_impl will be called by the apply method, after the arguments
// have been moved to the correct executor and the operators checked for
// conforming sizes.
//
// For simplicity, we assume that there is always only one right hand
// side and the stride of consecutive elements in the vectors is 1 (both
// of these are always true in this example).
void apply_impl(const gko::LinOp *b, gko::LinOp *x) const override
{
this->dist_mtx_->apply(b, x);
}


// There is also a version of the apply function which does the
// operation x = alpha * A * b + beta * x. This function is commonly
// used and can often be better optimized than implementing it using x =
// A * b. However, for simplicity, we will implement it exactly like
// that in this example.
void apply_impl(const gko::LinOp *alpha, const gko::LinOp *b,
const gko::LinOp *beta, gko::LinOp *x) const override
{
this->dist_mtx_->apply(alpha, b, beta, x);
}


private:
std::shared_ptr<dist_mtx> dist_mtx_;

std::shared_ptr<const SparsityPattern> local_sparsity_;

std::shared_ptr<const SparsityPattern> non_local_sparsity_;

std::shared_ptr<const CommunicationPattern> src_comm_pattern_;

std::vector<std::pair<bool, label>> local_interfaces_;
};


std::shared_ptr<gko::LinOp> create_distributed(
const ExecutorHandler &exec_handler, const Repartitioner &repartitioner,
std::shared_ptr<const HostMatrixWrapper> hostMatrix, word matrix_format)
{
if (matrix_format == "Coo") {
return RepartDistMatrix<gko::matrix::Coo<scalar, label>>::create(
exec_handler, repartitioner, hostMatrix);
}
if (matrix_format == "Csr") {
return RepartDistMatrix<gko::matrix::Csr<scalar, label>>::create(
exec_handler, repartitioner, hostMatrix);
}

return {};
}
Loading

0 comments on commit 88a9c83

Please sign in to comment.