In this tutorial the BLAS level 2 functionality in ViennaCL is demonstrated.
We start with including the required header files:
#include <iostream>
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/triangular.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <boost/numeric/ublas/vector_proxy.hpp>
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/io.hpp>
#define VIENNACL_WITH_UBLAS 1
using namespace boost::numeric;
We do not need any auxiliary functions in this example, so let us start directly in main():
Set up some uBLAS vectors and a matrix. They will be later used for filling the ViennaCL objects with data.
ublas::vector<ScalarType> rhs(12);
for (unsigned int i = 0; i < rhs.size(); ++i)
rhs(i) = randomNumber();
ublas::vector<ScalarType> rhs2 = rhs;
ublas::vector<ScalarType> result = ublas::zero_vector<ScalarType>(10);
ublas::vector<ScalarType> result2 = result;
ublas::vector<ScalarType> rhs_trans = rhs;
rhs_trans.resize(result.size(), true);
ublas::vector<ScalarType> result_trans = ublas::zero_vector<ScalarType>(rhs.size());
ublas::matrix<ScalarType> matrix(result.size(),rhs.size());
Fill the uBLAS-matrix
for (unsigned int i = 0; i < matrix.size1(); ++i)
for (unsigned int j = 0; j < matrix.size2(); ++j)
matrix(i,j) = randomNumber();
Use some plain STL types:
std::vector< ScalarType > stl_result(result.size());
std::vector< ScalarType > stl_rhs(rhs.size());
std::vector< std::vector<ScalarType> > stl_matrix(result.size());
for (unsigned int i=0; i < result.size(); ++i)
{
stl_matrix[i].resize(rhs.size());
for (unsigned int j = 0; j < matrix.size2(); ++j)
{
stl_rhs[j] = rhs[j];
stl_matrix[i][j] = matrix(i,j);
}
}
Set up some ViennaCL objects (initialized with zeros) and then copy data from the uBLAS objects.
Some basic matrix operations with ViennaCL are as follows:
vcl_matrix2 = vcl_matrix;
vcl_matrix2 += vcl_matrix;
vcl_matrix2 -= vcl_matrix;
vcl_matrix2 = vcl_matrix2 + vcl_matrix;
vcl_matrix2 = vcl_matrix2 - vcl_matrix;
vcl_matrix2 *= vcl_3;
vcl_matrix2 /= vcl_3;
A matrix can be cleared directly:
Other ways of data transfers between matrices in main memory and a ViennaCL matrix:
Matrix-Vector Products
Compute matrix-vector products
std::cout << "----- Matrix-Vector product -----" << std::endl;
Compute transposed matrix-vector products
std::cout << "----- Transposed Matrix-Vector product -----" << std::endl;
result_trans =
prod(
trans(matrix), rhs_trans);
viennacl::copy(rhs_trans.begin(), rhs_trans.end(), vcl_rhs_trans.begin());
Direct Solver
In order to demonstrate the direct solvers, we first need to setup suitable square matrices. This is again achieved by running the setup on the CPU and then copy the data over to ViennaCL types:
ublas::matrix<ScalarType> tri_matrix(10,10);
for (std::size_t i=0; i<tri_matrix.size1(); ++i)
{
for (std::size_t j=0; j<i; ++j)
tri_matrix(i,j) = 0.0;
for (std::size_t j=i; j<tri_matrix.size2(); ++j)
tri_matrix(i,j) = matrix(i,j);
}
rhs.resize(tri_matrix.size1(), true);
rhs2.resize(tri_matrix.size1(), true);
vcl_rhs.resize(tri_matrix.size1(), true);
vcl_result.resize(10);
Run a triangular solver on the upper triangular part of the matrix:
std::cout << "----- Upper Triangular solve -----" << std::endl;
Inplace variants of triangular solvers:
Set up a full system for full solver using LU factorizations:
std::cout << "----- LU factorization -----" << std::endl;
std::size_t lu_dim = 300;
ublas::matrix<ScalarType> square_matrix(lu_dim, lu_dim);
ublas::vector<ScalarType> lu_rhs(lu_dim);
for (std::size_t i=0; i<lu_dim; ++i)
for (std::size_t j=0; j<lu_dim; ++j)
square_matrix(i,j) = randomNumber();
for (std::size_t j=0; j<lu_dim; ++j)
{
lu_rhs(j) = randomNumber();
}
Full solver with Boost.uBLAS:
Full solver with ViennaCL:
That's it.
std::cout << "!!!! TUTORIAL COMPLETED SUCCESSFULLY !!!!" << std::endl;
return EXIT_SUCCESS;
}
Full Example Code
#include <iostream>
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/triangular.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <boost/numeric/ublas/vector_proxy.hpp>
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/io.hpp>
#define VIENNACL_WITH_UBLAS 1
using namespace boost::numeric;
{
ublas::vector<ScalarType> rhs(12);
for (unsigned int i = 0; i < rhs.size(); ++i)
rhs(i) = randomNumber();
ublas::vector<ScalarType> rhs2 = rhs;
ublas::vector<ScalarType> result = ublas::zero_vector<ScalarType>(10);
ublas::vector<ScalarType> result2 = result;
ublas::vector<ScalarType> rhs_trans = rhs;
rhs_trans.resize(result.size(), true);
ublas::vector<ScalarType> result_trans = ublas::zero_vector<ScalarType>(rhs.size());
ublas::matrix<ScalarType> matrix(result.size(),rhs.size());
for (unsigned int i = 0; i < matrix.size1(); ++i)
for (unsigned int j = 0; j < matrix.size2(); ++j)
matrix(i,j) = randomNumber();
std::vector< ScalarType > stl_result(result.size());
std::vector< ScalarType > stl_rhs(rhs.size());
std::vector< std::vector<ScalarType> > stl_matrix(result.size());
for (unsigned int i=0; i < result.size(); ++i)
{
stl_matrix[i].resize(rhs.size());
for (unsigned int j = 0; j < matrix.size2(); ++j)
{
stl_rhs[j] = rhs[j];
stl_matrix[i][j] = matrix(i,j);
}
}
vcl_matrix2 = vcl_matrix;
vcl_matrix2 += vcl_matrix;
vcl_matrix2 -= vcl_matrix;
vcl_matrix2 = vcl_matrix2 + vcl_matrix;
vcl_matrix2 = vcl_matrix2 - vcl_matrix;
vcl_matrix2 *= vcl_3;
vcl_matrix2 /= vcl_3;
vcl_matrix.clear();
std::cout << "----- Matrix-Vector product -----" << std::endl;
std::cout << "----- Transposed Matrix-Vector product -----" << std::endl;
result_trans =
prod(
trans(matrix), rhs_trans);
viennacl::copy(rhs_trans.begin(), rhs_trans.end(), vcl_rhs_trans.begin());
ublas::matrix<ScalarType> tri_matrix(10,10);
for (std::size_t i=0; i<tri_matrix.size1(); ++i)
{
for (std::size_t j=0; j<i; ++j)
tri_matrix(i,j) = 0.0;
for (std::size_t j=i; j<tri_matrix.size2(); ++j)
tri_matrix(i,j) = matrix(i,j);
}
rhs.resize(tri_matrix.size1(), true);
rhs2.resize(tri_matrix.size1(), true);
vcl_rhs.resize(tri_matrix.size1(), true);
vcl_result.resize(10);
std::cout << "----- Upper Triangular solve -----" << std::endl;
std::cout << "----- LU factorization -----" << std::endl;
std::size_t lu_dim = 300;
ublas::matrix<ScalarType> square_matrix(lu_dim, lu_dim);
ublas::vector<ScalarType> lu_rhs(lu_dim);
for (std::size_t i=0; i<lu_dim; ++i)
for (std::size_t j=0; j<lu_dim; ++j)
square_matrix(i,j) = randomNumber();
for (std::size_t j=0; j<lu_dim; ++j)
{
lu_rhs(j) = randomNumber();
}
std::cout << "!!!! TUTORIAL COMPLETED SUCCESSFULLY !!!!" << std::endl;
return EXIT_SUCCESS;
}