This tutorial shows the use of algebraic multigrid (AMG) preconditioners.
- Warning
- AMG is currently only experimentally available with the OpenCL backend and depends on Boost.uBLAS
We start with some rather general includes and preprocessor variables:
Import the AMG functionality:
Some more includes:
#include <iostream>
#include <vector>
#include <ctime>
Part 1: Worker routines
Run the Solver
Runs the provided solver specified in the solver
object with the provided preconditioner precond
template<typename MatrixType, typename VectorType, typename SolverTag, typename PrecondTag>
void run_solver(MatrixType
const & matrix, VectorType
const & rhs, VectorType
const & ref_result, SolverTag
const & solver, PrecondTag
const & precond)
{
VectorType result(rhs);
VectorType residual(rhs);
std::cout <<
" > Solver time: " << timer.
get() << std::endl;
std::cout << " > Iterations: " << solver.iters() << std::endl;
result -= ref_result;
}
Compare AMG preconditioner for uBLAS and ViennaCL types
The AMG implementations in ViennaCL can be used with uBLAS types as well as ViennaCL types. This function compares the two in terms of execution time.
template<typename ScalarType>
std::string info,
{
std::cout << "-- CG with AMG preconditioner, " << info << " --" << std::endl;
std::cout << " * Setup phase (ViennaCL types)..." << std::endl;
vcl_amg.setup();
std::cout <<
" > Setup time: " << timer.
get() << std::endl;
std::cout << " * CG solver (ViennaCL types)..." << std::endl;
run_solver(vcl_compressed_matrix, vcl_vec, vcl_result, cg_solver, vcl_amg);
}
Part 2: Run Solvers with AMG Preconditioners
In this
int main(
int argc,
char **argv)
{
std::string filename("../examples/testdata/mat65k.mtx");
if (argc == 2)
filename = argv[1];
Print some device info at the beginning. If there is more than one OpenCL device available, use the second device.
std::cout << std::endl;
std::cout << "----------------------------------------------" << std::endl;
std::cout << " Device Info" << std::endl;
std::cout << "----------------------------------------------" << std::endl;
#ifdef VIENNACL_WITH_OPENCL
std::vector<viennacl::ocl::device>
const & devices = pf.
devices();
if (devices.size() > 1)
else
#else
#endif
Set up the matrices and vectors for the iterative solvers (cf. iterative.cpp)
std::cout << "Reading matrix..." << std::endl;
std::vector< std::map<unsigned int, ScalarType> > read_in_matrix;
{
std::cout << "Error reading Matrix file" << std::endl;
return EXIT_FAILURE;
}
std::cout << "Reading matrix completed." << std::endl;
std::vector<ScalarType> std_vec, std_result;
std_vec.
resize(vcl_compressed_matrix.size1());
std_result.
resize(vcl_compressed_matrix.size1());
for (std::size_t i=0; i<std_result.
size(); ++i)
Instantiate a tag for the conjugate gradient solver, the AMG preconditioner tag, and create an AMG preconditioner object:
Run solver without preconditioner. This serves as a baseline for comparison. Note that iterative solvers without preconditioner on GPUs can be very efficient because they map well to the massively parallel hardware.
std::cout << "-- CG solver (no preconditioner, warmup) --" << std::endl;
Generate the setup for an AMG preconditioner of Ruge-Stueben type with only one pass and direct interpolation (ONEPASS+DIRECT)
run_amg(cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "ONEPASS COARSENING, DIRECT INTERPOLATION", amg_tag_direct);
Generate the setup for an aggregation-based AMG preconditioner with unsmoothed aggregation
run_amg(cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "AG COARSENING (PMIS), AG INTERPOLATION", amg_tag_agg_pmis);
Generate the setup for a smoothed aggregation AMG preconditioner
run_amg (cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "AG COARSENING (PMIS), SA INTERPOLATION", amg_tag_sa_pmis);
std::cout << std::endl;
std::cout << " -------------- Benchmark runs -------------- " << std::endl;
std::cout << std::endl;
std::cout << "-- CG solver (no preconditioner) --" << std::endl;
run_amg(cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "ONEPASS COARSENING, DIRECT INTERPOLATION", amg_tag_direct);
run_amg(cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "AG COARSENING (PMIS), AG INTERPOLATION", amg_tag_agg_pmis);
run_amg (cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "AG COARSENING (PMIS), SA INTERPOLATION", amg_tag_sa_pmis);
That's it.
std::cout << "!!!! TUTORIAL COMPLETED SUCCESSFULLY !!!!" << std::endl;
return EXIT_SUCCESS;
}
Full Example Code
#include <iostream>
#include <vector>
#include <ctime>
template<typename MatrixType, typename VectorType, typename SolverTag, typename PrecondTag>
void run_solver(MatrixType
const & matrix, VectorType
const & rhs, VectorType
const & ref_result, SolverTag
const & solver, PrecondTag
const & precond)
{
VectorType result(rhs);
VectorType residual(rhs);
std::cout <<
" > Solver time: " << timer.
get() << std::endl;
std::cout << " > Iterations: " << solver.iters() << std::endl;
result -= ref_result;
}
template<typename ScalarType>
std::string info,
{
std::cout << "-- CG with AMG preconditioner, " << info << " --" << std::endl;
std::cout << " * Setup phase (ViennaCL types)..." << std::endl;
vcl_amg.setup();
std::cout <<
" > Setup time: " << timer.
get() << std::endl;
std::cout << " * CG solver (ViennaCL types)..." << std::endl;
run_solver(vcl_compressed_matrix, vcl_vec, vcl_result, cg_solver, vcl_amg);
}
int main(
int argc,
char **argv)
{
std::string filename("../examples/testdata/mat65k.mtx");
if (argc == 2)
filename = argv[1];
std::cout << std::endl;
std::cout << "----------------------------------------------" << std::endl;
std::cout << " Device Info" << std::endl;
std::cout << "----------------------------------------------" << std::endl;
#ifdef VIENNACL_WITH_OPENCL
std::vector<viennacl::ocl::device>
const & devices = pf.
devices();
if (devices.size() > 1)
else
#else
#endif
std::cout << "Reading matrix..." << std::endl;
std::vector< std::map<unsigned int, ScalarType> > read_in_matrix;
{
std::cout << "Error reading Matrix file" << std::endl;
return EXIT_FAILURE;
}
std::cout << "Reading matrix completed." << std::endl;
std::vector<ScalarType> std_vec, std_result;
for (std::size_t i=0; i<std_result.
size(); ++i)
std::cout << "-- CG solver (no preconditioner, warmup) --" << std::endl;
run_amg(cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "ONEPASS COARSENING, DIRECT INTERPOLATION", amg_tag_direct);
run_amg(cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "AG COARSENING (PMIS), AG INTERPOLATION", amg_tag_agg_pmis);
run_amg (cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "AG COARSENING (PMIS), SA INTERPOLATION", amg_tag_sa_pmis);
std::cout << std::endl;
std::cout << " -------------- Benchmark runs -------------- " << std::endl;
std::cout << std::endl;
std::cout << "-- CG solver (no preconditioner) --" << std::endl;
run_amg(cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "ONEPASS COARSENING, DIRECT INTERPOLATION", amg_tag_direct);
run_amg(cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "AG COARSENING (PMIS), AG INTERPOLATION", amg_tag_agg_pmis);
run_amg (cg_solver, vcl_vec, vcl_result, vcl_compressed_matrix, "AG COARSENING (PMIS), SA INTERPOLATION", amg_tag_sa_pmis);
std::cout << "!!!! TUTORIAL COMPLETED SUCCESSFULLY !!!!" << std::endl;
return EXIT_SUCCESS;
}