Ginkgo: The custom-stopping-criterion program

| Ginkgo Generated from branch based on main. Ginkgo version 1.11.0 A numerical linear algebra library targeting many-core architectures

Loading...
Searching...
No Matches
The custom-stopping-criterion program

The custom stopping criterion creation example.

This example depends on simple-solver, minimal-cuda-solver.

Table of contents
Introduction About the example The commented program | Results Comments about programming and debugging The plain program

# Introduction

### About the example

# The commented program

};
GKO_ENABLE_CRITERION_FACTORY(ByInteraction, parameters, Factory);
GKO_ENABLE_BUILD_METHOD(Factory);
protected:
bool check_impl(gko::uint8 stoppingId, bool setFinalized,
gko::array<gko::stopping_status>* stop_status,
bool* one_changed, const Criterion::Updater&) override
{
bool result = *(parameters_.stop_iteration_process);
if (result) {
this->set_all_statuses(stoppingId, setFinalized, stop_status);
*one_changed = true;
}
return result;
}
explicit ByInteraction(std::shared_ptr<const gko::Executor> exec)
: EnablePolymorphicObject<ByInteraction, Criterion>(std::move(exec))
{}
explicit ByInteraction(const Factory* factory,
const gko::stop::CriterionArgs& args)
: EnablePolymorphicObject<ByInteraction, Criterion>(
factory->get_executor()),
parameters_{factory->get_parameters()}
{}
};
void run_solver(volatile bool* stop_iteration_process,
std::shared_ptr<gko::Executor> exec)
{
gko::array
An array is a container which encapsulates fixed-sized arrays, stored on the Executor tied to the arr...
Definition array.hpp:166
GKO_ENABLE_BUILD_METHOD
#define GKO_ENABLE_BUILD_METHOD(_factory_name)
Defines a build method for the factory, simplifying its construction by removing the repetitive typin...
Definition abstract_factory.hpp:394
gko::log::profile_event_category::factory
@ factory
LinOpFactory events.
Definition profiler_hook.hpp:32
gko::uint8
std::uint8_t uint8
8-bit unsigned integral type.
Definition types.hpp:119
std
STL namespace.
gko::stop::CriterionArgs
This struct is used to pass parameters to the EnableDefaultCriterionFactoryCriterionFactory::generate...
Definition criterion.hpp:205

Some shortcuts

using ValueType = double;
using RealValueType = gko::remove_complex<ValueType>;
using IndexType = int;
using mtx = gko::matrix::Csr<ValueType, IndexType>;
using vec = gko::matrix::Dense<ValueType>;
using real_vec = gko::matrix::Dense<RealValueType>;
using bicg = gko::solver::Bicgstab<ValueType>;
gko::matrix::Csr
CSR is a matrix format which stores only the nonzero coefficients by compressing each row of the matr...
Definition csr.hpp:126
gko::matrix::Dense
Dense is a matrix format which explicitly stores all values of the matrix.
Definition dense.hpp:120
gko::solver::Bicgstab
BiCGSTAB or the Bi-Conjugate Gradient-Stabilized is a Krylov subspace solver.
Definition bicgstab.hpp:55
gko::remove_complex
typename detail::remove_complex_s< T >::type remove_complex
Obtain the type which removed the complex of complex/scalar type or the template parameter of class b...
Definition math.hpp:264

Read Data

auto A = share(gko::read<mtx>(std::ifstream("data/A.mtx"), exec));
auto b = gko::read<vec>(std::ifstream("data/b.mtx"), exec);
auto x = gko::read<vec>(std::ifstream("data/x0.mtx"), exec);
gko::read
std::unique_ptr< MatrixType > read(StreamType &&is, MatrixArgs &&... args)
Reads a matrix stored in matrix market format from an input stream.
Definition mtx_io.hpp:160

Create solver factory and solve system

auto solver =
bicg::build()
.with_criteria(ByInteraction::build().with_stop_iteration_process(
stop_iteration_process))
.on(exec)
->generate(A);
solver->add_logger(gko::log::Stream<ValueType>::create(
gko::log::Logger::iteration_complete_mask, std::cout, true));
solver->apply(b, x);
std::cout << "Solver stopped" << std::endl;
gko::log::Stream::create
static std::unique_ptr< Stream > create(std::shared_ptr< const Executor > exec, const Logger::mask_type &enabled_events=Logger::all_events_mask, std::ostream &os=std::cout, bool verbose=false)
Creates a Stream logger.
Definition stream.hpp:172

Print solution

std::cout << "Solution (x): \n";
write(std::cout, x);

Calculate residual

auto one = gko::initialize<vec>({1.0}, exec);
auto neg_one = gko::initialize<vec>({-1.0}, exec);
auto res = gko::initialize<real_vec>({0.0}, exec);
A->apply(one, x, neg_one, b);
b->compute_norm2(res);
std::cout << "Residual norm sqrt(r^T r): \n";
write(std::cout, res);
}
int main(int argc, char* argv[])
{
gko::initialize
std::unique_ptr< Matrix > initialize(size_type stride, std::initializer_list< typename Matrix::value_type > vals, std::shared_ptr< const Executor > exec, TArgs &&... create_args)
Creates and initializes a column-vector.
Definition dense.hpp:1593
gko::write
void write(StreamType &&os, MatrixPtrType &&matrix, layout_type layout=detail::mtx_io_traits< std::remove_cv_t< detail::pointee< MatrixPtrType > > >::default_layout)
Writes a matrix into an output stream in matrix market format.
Definition mtx_io.hpp:299

Print version information

std::cout << gko::version_info::get() << std::endl;
gko::version_info::get
static const version_info & get()
Returns an instance of version_info.
Definition version.hpp:139

Figure out where to run the code

if (argc == 2 && (std::string(argv[1]) == "--help")) {
std::cerr << "Usage: " << argv[0] << " [executor]" << std::endl;
std::exit(-1);
}

Figure out where to run the code

const auto executor_string = argc >= 2 ? argv[1] : "reference";

Figure out where to run the code

std::map<std::string, std::function<std::shared_ptr<gko::Executor>()>>
exec_map{
{"omp", [] { return gko::OmpExecutor::create(); }},
{"cuda",
[] {
return gko::CudaExecutor::create(0,
gko::OmpExecutor::create());
}},
{"hip",
[] {
return gko::HipExecutor::create(0, gko::OmpExecutor::create());
}},
{"dpcpp",
[] {
return gko::DpcppExecutor::create(0,
gko::OmpExecutor::create());
}},
{"reference", [] { return gko::ReferenceExecutor::create(); }}};
gko::CudaExecutor::create
static std::shared_ptr< CudaExecutor > create(int device_id, std::shared_ptr< Executor > master, bool device_reset, allocation_mode alloc_mode=default_cuda_alloc_mode, CUstream_st *stream=nullptr)
Creates a new CudaExecutor.
gko::DpcppExecutor::create
static std::shared_ptr< DpcppExecutor > create(int device_id, std::shared_ptr< Executor > master, std::string device_type="all", dpcpp_queue_property property=dpcpp_queue_property::in_order)
Creates a new DpcppExecutor.
gko::HipExecutor::create
static std::shared_ptr< HipExecutor > create(int device_id, std::shared_ptr< Executor > master, bool device_reset, allocation_mode alloc_mode=default_hip_alloc_mode, CUstream_st *stream=nullptr)
Creates a new HipExecutor.
gko::OmpExecutor::create
static std::shared_ptr< OmpExecutor > create(std::shared_ptr< CpuAllocatorBase > alloc=std::make_shared< CpuAllocator >())
Creates a new OmpExecutor.
Definition executor.hpp:1396

executor where Ginkgo will perform the computation

const auto exec = exec_map.at(executor_string)(); // throws if not valid

Declare a user controlled boolean for the iteration process

volatile bool stop_iteration_process{};

Create a new a thread to launch the solver

std::thread t(run_solver, &stop_iteration_process, exec);

Look for an input command "stop" in the console, which sets the boolean to true

std::cout << "Type 'stop' to stop the iteration process" << std::endl;
std::string command;
while (std::cin >> command) {
if (command == "stop") {
break;
} else {
std::cout << "Unknown command" << std::endl;
}
}
std::cout << "User input command 'stop' - The solver will stop!"
<< std::endl;
stop_iteration_process = true;
t.join();
}

# Results

This is the expected output:

.
.
.
.
.
.
[LOG] >>> iteration 22516 completed with solver LinOp[gko::solver::Bicgstab<double>,0x7fe6a4003710] with residual LinOp[gko::matrix::Dense<double>,0x7fe6a40050b0], solution LinOp[gko::matrix::Dense<double>,0x7fe6a40048e0] and residual_norm LinOp[gko::LinOp const*,0]
LinOp[gko::matrix::Dense<double>,0x7fe6a40050b0][
5.17803e-164
-7.6865e-165
-2.06149e-164
-4.84737e-165
-3.36597e-164
2.22353e-164
1.47594e-165
-1.78592e-165
-6.17274e-166
-3.02681e-166
7.82009e-166
8.57102e-165
-1.28879e-164
-2.62076e-165
2.55329e-165
-5.95988e-166
-5.79273e-166
-5.20172e-166
-6.79458e-166
]
// Typing 'stop' stops the solver.
User input command 'stop' - The solver will stop
LinOp[gko::matrix::Dense<double>,0x7fe6a40048e0][
0.252218
0.108645
0.0662811
0.0630433
0.0384088
0.0396536
0.0402648
0.0338935
0.0193098
0.0234653
0.0211499
0.0196413
0.0199151
0.0181674
0.0162722
0.0150714
0.0107016
0.0121141
0.0123025
]
Solver stopped
Solution (x):
%%MatrixMarket matrix array real general
19 1
0.252218
0.108645
0.0662811
0.0630433
0.0384088
0.0396536
0.0402648
0.0338935
0.0193098
0.0234653
0.0211499
0.0196413
0.0199151
0.0181674
0.0162722
0.0150714
0.0107016
0.0121141
0.0123025
Residual norm sqrt(r^T r):
%%MatrixMarket matrix array real general
1 1
6.50306e-16
gko::LinOp
Definition lin_op.hpp:117

### Comments about programming and debugging

# The plain program

#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <thread>
#include <ginkgo/ginkgo.hpp>
class ByInteraction
: public gko::EnablePolymorphicObject<ByInteraction, gko::stop::Criterion> {
friend class gko::EnablePolymorphicObject<ByInteraction,
gko::stop::Criterion>;
using Criterion = gko::stop::Criterion;
public:
GKO_CREATE_FACTORY_PARAMETERS(parameters, Factory)
{
std::add_pointer<volatile bool>::type GKO_FACTORY_PARAMETER_SCALAR(
stop_iteration_process, nullptr);
};
GKO_ENABLE_CRITERION_FACTORY(ByInteraction, parameters, Factory);
GKO_ENABLE_BUILD_METHOD(Factory);
protected:
bool check_impl(gko::uint8 stoppingId, bool setFinalized,
gko::array<gko::stopping_status>* stop_status,
bool* one_changed, const Criterion::Updater&) override
{
bool result = *(parameters_.stop_iteration_process);
if (result) {
this->set_all_statuses(stoppingId, setFinalized, stop_status);
*one_changed = true;
}
return result;
}
explicit ByInteraction(std::shared_ptr<const gko::Executor> exec)
: EnablePolymorphicObject<ByInteraction, Criterion>(std::move(exec))
{}
explicit ByInteraction(const Factory* factory,
const gko::stop::CriterionArgs& args)
: EnablePolymorphicObject<ByInteraction, Criterion>(
factory->get_executor()),
parameters_{factory->get_parameters()}
{}
};
void run_solver(volatile bool* stop_iteration_process,
std::shared_ptr<gko::Executor> exec)
{
using ValueType = double;
using RealValueType = gko::remove_complex<ValueType>;
using IndexType = int;
using mtx = gko::matrix::Csr<ValueType, IndexType>;
using vec = gko::matrix::Dense<ValueType>;
using real_vec = gko::matrix::Dense<RealValueType>;
using bicg = gko::solver::Bicgstab<ValueType>;
auto A = share(gko::read<mtx>(std::ifstream("data/A.mtx"), exec));
auto b = gko::read<vec>(std::ifstream("data/b.mtx"), exec);
auto x = gko::read<vec>(std::ifstream("data/x0.mtx"), exec);
auto solver =
bicg::build()
.with_criteria(ByInteraction::build().with_stop_iteration_process(
stop_iteration_process))
.on(exec)
->generate(A);
solver->add_logger(gko::log::Stream<ValueType>::create(
gko::log::Logger::iteration_complete_mask, std::cout, true));
solver->apply(b, x);
std::cout << "Solver stopped" << std::endl;
std::cout << "Solution (x): \n";
write(std::cout, x);
auto one = gko::initialize<vec>({1.0}, exec);
auto neg_one = gko::initialize<vec>({-1.0}, exec);
auto res = gko::initialize<real_vec>({0.0}, exec);
A->apply(one, x, neg_one, b);
b->compute_norm2(res);
std::cout << "Residual norm sqrt(r^T r): \n";
write(std::cout, res);
}
int main(int argc, char* argv[])
{
std::cout << gko::version_info::get() << std::endl;
if (argc == 2 && (std::string(argv[1]) == "--help")) {
std::cerr << "Usage: " << argv[0] << " [executor]" << std::endl;
std::exit(-1);
}
const auto executor_string = argc >= 2 ? argv[1] : "reference";
std::map<std::string, std::function<std::shared_ptr<gko::Executor>()>>
exec_map{
{"omp", [] { return gko::OmpExecutor::create(); }},
{"cuda",
[] {
return gko::CudaExecutor::create(0,
gko::OmpExecutor::create());
}},
{"hip",
[] {
return gko::HipExecutor::create(0, gko::OmpExecutor::create());
}},
{"dpcpp",
[] {
return gko::DpcppExecutor::create(0,
gko::OmpExecutor::create());
}},
{"reference", [] { return gko::ReferenceExecutor::create(); }}};
const auto exec = exec_map.at(executor_string)(); // throws if not valid
volatile bool stop_iteration_process{};
std::thread t(run_solver, &stop_iteration_process, exec);
std::cout << "Type 'stop' to stop the iteration process" << std::endl;
std::string command;
while (std::cin >> command) {
if (command == "stop") {
break;
} else {
std::cout << "Unknown command" << std::endl;
}
}
std::cout << "User input command 'stop' - The solver will stop!"
<< std::endl;
stop_iteration_process = true;
t.join();
}
gko::EnablePolymorphicObject
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:668
gko::stop::Criterion
The Criterion class is a base class for all stopping criteria.
Definition criterion.hpp:36
GKO_CREATE_FACTORY_PARAMETERS
#define GKO_CREATE_FACTORY_PARAMETERS(_parameters_name, _factory_name)
This Macro will generate a new type containing the parameters for the factory _factory_name.
Definition abstract_factory.hpp:280
GKO_FACTORY_PARAMETER_SCALAR
#define GKO_FACTORY_PARAMETER_SCALAR(_name, _default)
Creates a scalar factory parameter in the factory parameters structure.
Definition abstract_factory.hpp:445
gko::log::profile_event_category::solver
@ solver
Solver events.
Definition profiler_hook.hpp:34
gko
The Ginkgo namespace.
Definition abstract_factory.hpp:20
gko::one
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:654
gko::share
detail::shared_type< OwningPointer > share(OwningPointer &&p)
Marks the object pointed to by p as shared.
Definition utils_helper.hpp:224