monolish  0.17.1
MONOlithic LInear equation Solvers for Highly-parallel architecture
CPU Examples

Namespace and header files

The monolish namespace contains monolish::vector and monolish::view1D. monolish has the following 7 namespaces in addition to the monolish namespace:

This chapter describes a sample program using monolish that runs on the CPU.

Sample programs that run on the GPU can be found at examples/. They work on CPU and GPU. The programs running on the GPU are described in the next chapter.

Sample programs for CPU can be found at examples/cpu_only. They only work on the CPU.

Compute innerproduct

First, a simple inner product program is shown below:

#include <iostream>
int main() {
// Output log if you need
// monolish::util::set_log_level(3);
// monolish::util::set_log_filename("./monolish_test_log.txt");
size_t N = 100;
// x = {1,1,...,1}, length N
// Random vector length N with random values in the range 1.0 to 2.0
// Random seed is 123 (mt19937)
monolish::vector<double> y(N, 1.0, 2.0, 123);
// compute innerproduct
double ans = monolish::blas::dot(x, y);
std::cout << ans << std::endl;
return 0;
}
void dot(const vector< double > &x, const vector< double > &y, double &ans)
inner product (dot)

This program can be compiled by the following command.

g++ -O3 innerproduct.cpp -o innerproduct_cpu.out -lmonolish_cpu

The following command runs this.

./innerproduct_cpu.out

A description of this program is given below:

This program is executed in parallel. The number of threads is specified by the OMP_NUM_THREADS environment variable.

Solve Ax=b

The following is a sample program that solves a linear equation; Ax=b using the conjugate gradient method with jacobi preconditioner.

#include <iostream>
int main() {
// Output log if you need
// monolish::util::set_log_level(3);
// monolish::util::set_log_filename("./monolish_test_log.txt");
monolish::matrix::COO<double> A_COO("sample.mtx"); // Input from file
// Edit the matrix as needed //
// Execute A_COO.sort() after editing the matrix //
// Create CRS format matrix and convert from COO format matrix
// Length A.row()
// Random vector length A.row() with random values in the range 1.0 to 2.0
// Random seeds are 123 and 321 (mt19937)
monolish::vector<double> x(A.get_row(), 1.0, 2.0, 123);
monolish::vector<double> b(A.get_row(), 1.0, 2.0, 321);
// Create CG class
// create jacobi preconditioner
// Set preconditioner to CG solver
solver.set_create_precond(precond);
solver.set_apply_precond(precond);
// Set solver options
solver.set_tol(1.0e-12);
solver.set_maxiter(A.get_row());
// if you need residual history
// solver.set_print_rhistory(true);
// solver.set_rhistory_filename("./a.txt");
// Solve Ax=b by CG with jacobi
if (monolish::util::solver_check(solver.solve(A, x, b))) {
return 1;
}
// Show answer
x.print_all();
return 0;
}
int solve(MATRIX &A, vector< Float > &x, vector< Float > &b)
solve Ax = b by BiCGSTAB method(lib=0: monolish)
Coodinate (COO) format Matrix (need to sort)
Compressed Row Storage (CRS) format Matrix.
void set_tol(double t)
set tolerance (default:1.0e-8)
void set_apply_precond(PRECOND &p)
set precondition apply function
void set_maxiter(size_t max)
set max iter. (default = SIZE_MAX)
void set_create_precond(PRECOND &p)
set precondition create function
bool solver_check(const int err)
check error

Matrix creation

monolish::matrix::COO has editable attribute, so users can edit any element using insert() and monolish::matrix::COO.at() "at()" functions. COO can be created by giving array pointer or file name to the constructor, too. This sample program creates a matrix from a file. The input file format is MatrixMarket format. MatrixMarket format is a common data format for sparse matrices. scipy can also output matrices in MatrixMarket format.

monolish::matrix::CRS can easily be generated by taking COO as an argument to the constructor.

Solving Ax=b

monolish proposes a new way to implement linear solvers.

Applying preconditioning means combining multiple solvers. In other words, the solver and preconditioner in the Krylov subspace method are essentially the same thing.

The solver classes included in monolish::equation all have the following functions:

  • solve() : Solve the simultaneous linear equations.
  • create_precond() : Create the preconditioning matrix M.
  • apply_precond() : Apply preconditioner according to the created preprocessing matrix M.
  • set_create_precond() : Register another class' create_precond to the class as a function to create the preprocessing matrix.
  • set_apply_precond() : Register "apply_precond" of another class to the class as a function to apply preprocessing.

The class that executes solve() execute the registered create_precond() and apply_precond(). If no preconditioner is registered, it calls monolish::equation::none as "none preconditioner".

By being able to register the creation and application of preconditioners separately, users can use the preconditioner matrix in different ways.

In the current version, the create_precond() and apply_precond() functions of some classes do not work. In the future, we will make these functions work in all classes. This implementation would be very efficient for multi-grid methods.

See here for a list of solvers.

Improve solver program

The program in the previous chapter has the matrix storage format, data type, solver name, and preconditioner name explicitly specified all over the program.

If users want to change them depending on the input matrix, this implementation requires a lot of program changes.

Since monolish is designed so that the matrix and solver classes all have the same interface, these changes can be eliminated by templating.

A templated program is shown below.

#include <iostream>
// Template a matrix format, solver and preconditioer.
template <typename MATRIX, typename SOLVER, typename PRECOND, typename FLOAT>
void solve() {
monolish::matrix::COO<FLOAT> A_COO("sample.mtx"); // Input from file
// Edit the matrix as needed //
// Execute A_COO.sort() after editing the matrix //
// Create CRS format matrix and convert from COO format matrix
MATRIX A(A_COO);
// Length A.row()
// Random vector length A.row() with random values in the range 1.0 to 2.0
// Random seeds are 123 and 321 (mt19937)
monolish::vector<FLOAT> x(A.get_row(), 1.0, 2.0, 123);
monolish::vector<FLOAT> b(A.get_row(), 1.0, 2.0, 321);
// Create solver
SOLVER solver;
// Create preconditioner
PRECOND precond;
solver.set_create_precond(precond);
solver.set_apply_precond(precond);
// Set solver options
solver.set_tol(1.0e-12);
solver.set_maxiter(A.get_row());
// if you need residual history
// solver.set_print_rhistory(true);
// solver.set_rhistory_filename("./a.txt");
// Solve
if (monolish::util::solver_check(solver.solve(A, x, b))) {
return;
}
// output x to standard output
x.print_all();
}
int main() {
// output log if you need
// monolish::util::set_log_level(3);
// monolish::util::set_log_filename("./monolish_test_log.txt");
std::cout
<< "A is CRS, solver is CG, precondition is Jacobi, precision is double"
<< std::endl;
solve<monolish::matrix::CRS<double>,
double>();
std::cout << "A is Dense, solver is BiCGSTAB, precondition is none, "
"precision is float"
<< std::endl;
solve<monolish::matrix::Dense<float>,
float>();
std::cout
<< "A is Dense, solver is LU, precondition is none, precision is double"
<< std::endl;
solve<monolish::matrix::Dense<double>,
double>();
return 0;
}
none solver class(nothing to do)

This program is templated so that the function that solves Ax=b is not oblivious to the matrix storage format or data type.