Boost logo

Ublas :

From: dariomt_at_[hidden]
Date: 2008-01-18 06:00:07


*guwi17_at_[hidden] wrote:

*>BTW. I would not expect a big difference between a banded matrix with
>compile time known bandwidth compared to the current implementation. I
>still wait for someone who proves the opposite ;-)
>
>Do you already have a benchmark to measure the speed of banded_matrix?

I am doing a very simple test with the (undocumented?) diagonal_matrix in
banded.hpp

A matrix product of two diagonal_matrix should return another
diagonal_matrix and should have linear complexity O(size). The same goes for
an element-wise vector product. Storage should not be an issue, as the data
layout of the diagonal_matrix should match that of the vector.

The test performs one of both, and time measurements for a size of 1E7
double elements shows that the vector product is 10 times faster. The test
also uses a matrix_vector_slice to get a view of the diagonal_matrix as a
vector and does an element-wise product. This is much faster that the matrix
product, but vector product is still twice as fast.

IMO compile time knowledge of the bandwith of a banded_matrix *IS*
important, specially for large sizes and small bandwidth (being a large
diagonal_matrix the extreme case).

I suppose that implementing a banded_matrix_c with compile time bandwith is
not trivial, at least not if optimal traversal of elements is required...

test code:

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <boost/numeric/ublas/banded.hpp>

#ifdef NDEBUG
    const int SIZE = 10000000;
#else
    const int SIZE = 10;
#endif

void diagonal()
{
    using namespace boost::numeric::ublas;
    diagonal_matrix<double> d1 ( SIZE );
    diagonal_matrix<double> d2 ( SIZE );

    // how to do this with diagonal_adaptor<scalar_matrix> ?
    std::fill(d1.data().begin(), d1.data().end(), 2.0);
    std::fill(d2.data().begin(), d2.data().end(), 10.0);

    diagonal_matrix<double> d3 = prod(d1,d2);
}

void diagonal_as_vector()
{
    using namespace boost::numeric::ublas;
    diagonal_matrix<double> d1 ( SIZE );
    diagonal_matrix<double> d2 ( SIZE );

    // how to do this with diagonal_adaptor<scalar_matrix> ?
    std::fill(d1.data().begin(), d1.data().end(), 2.0);
    std::fill(d2.data().begin(), d2.data().end(), 10.0);

    matrix_vector_slice< diagonal_matrix<double> > dx1(d1, slice(0,1,SIZE),
slice(0,1,SIZE));
    matrix_vector_slice< diagonal_matrix<double> > dx2(d2, slice(0,1,SIZE),
slice(0,1,SIZE));

    // any vector_expression to diagonal_matrix ?
    vector<double> d3 = element_prod(dx1, dx2);
}

void vectors()
{
    using namespace boost::numeric::ublas;
    vector<double> v1(scalar_vector<double>(SIZE, 2.0));
    vector<double> v2(scalar_vector<double>(SIZE, 10.0));
    vector<double> v3 = element_prod(v1, v2);
}

int main(int argc, char* argv[])
{
    if (argc != 2) return 1;
    if (*argv[1] == 'd') diagonal();
    else if (*argv[1] == 'v') vectors();
    else if (*argv[1] == 'x') diagonal_as_vector();
    return 0;
}