Ginkgo Generated from branch based on master. Ginkgo version 1.7.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
  1. Introduction
  2. The commented program
  1. Results
  2. The plain program

Introduction

About the example

The commented program

#include <ginkgo/ginkgo.hpp>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <thread>
/ **
* The ByInteraction class is a criterion which asks for user input to stop
* the iteration process. Using this criterion is slightly more complex than the
* other ones, because it is asynchronous therefore requires the use of threads.
* /
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)
{
/ **
* Boolean set by the user to stop the iteration process
* /
std::add_pointer<volatile bool>::type GKO_FACTORY_PARAMETER_SCALAR(
stop_iteration_process, nullptr);
};
GKO_ENABLE_CRITERION_FACTORY(ByInteraction, parameters, Factory);
protected:
bool check_impl(gko::uint8 stoppingId, bool setFinalized,
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,
: EnablePolymorphicObject<ByInteraction, Criterion>(
factory->get_executor()),
parameters_{factory->get_parameters()}
{}
};
void run_solver(volatile bool* stop_iteration_process,
std::shared_ptr<gko::Executor> exec)
{
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:691
An array is a container which encapsulates fixed-sized arrays, stored on the Executor tied to the arr...
Definition array.hpp:187
The Criterion class is a base class for all stopping criteria.
Definition criterion.hpp:64
#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:308
#define GKO_FACTORY_PARAMETER_SCALAR(_name, _default)
Creates a scalar factory parameter in the factory parameters structure.
Definition abstract_factory.hpp:473
#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:422
@ factory
LinOpFactory events.
The Ginkgo namespace.
Definition abstract_factory.hpp:48
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:803
std::uint8_t uint8
8-bit unsigned integral type.
Definition types.hpp:149
This struct is used to pass parameters to the EnableDefaultCriterionFactoryCriterionFactory::generate...
Definition criterion.hpp:233

Some shortcuts

using ValueType = double;
using RealValueType = gko::remove_complex<ValueType>;
using IndexType = int;
CSR is a matrix format which stores only the nonzero coefficients by compressing each row of the matr...
Definition csr.hpp:146
Dense is a matrix format which explicitly stores all values of the matrix.
Definition dense.hpp:136
BiCGSTAB or the Bi-Conjugate Gradient-Stabilized is a Krylov subspace solver.
Definition bicgstab.hpp:82
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:354

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);

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);
gko::log::Logger::iteration_complete_mask, std::cout, true));
solver->apply(b, x);
std::cout << "Solver stopped" << std::endl;
Stream is a Logger which logs every event to a stream.
Definition stream.hpp:59

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[])
{
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:324

Print version information

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

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",
[] {
}},
{"hip",
[] {
}},
{"dpcpp",
[] {
}},
{"reference", [] { return gko::ReferenceExecutor::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.
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.
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.
static std::shared_ptr< OmpExecutor > create(std::shared_ptr< CpuAllocatorBase > alloc=std::make_shared< CpuAllocator >())
Creates a new OmpExecutor.
Definition executor.hpp:1373

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
Definition lin_op.hpp:146

Comments about programming and debugging

The plain program

/*******************************<GINKGO LICENSE>******************************
Copyright (c) 2017-2023, the Ginkgo authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************<GINKGO LICENSE>*******************************/
#include <ginkgo/ginkgo.hpp>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <thread>
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);
protected:
bool check_impl(gko::uint8 stoppingId, bool setFinalized,
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,
: 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;
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);
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",
[] {
}},
{"hip",
[] {
}},
{"dpcpp",
[] {
}},
{"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();
}
detail::shared_type< OwningPointer > share(OwningPointer &&p)
Marks the object pointed to by p as shared.
Definition utils_helper.hpp:254