I decided to experiment with Atlas (Automatically Tuned Linear Algebra Software) because it contains a parallel BLAS library. For those that don’t have access to the Intel math kernel library Atlas is a good choice for obtaining an automatically optimized BLAS library. It also provides a nice C interface to BLAS, hence there are two ways to go about using the library. On my Fedora 18 the Atlas build is found under “/usr/lib64/atlas/”. I’ll start with a short example of how to scale a vector.
Without cblas.h
#include <stdio.h> int main () { int i, j, n, one; double coefficient; double x[] = { 1, 1, 1 }; coefficient = 4.323; one = 1; n = 3; dscal_(&n, &coefficient, &x[0], &one); for (i = 0; i < 3; ++i) printf ("%f\n", x[i]); return 0; }
Calling Fortran from C
The Fortran compiler appends an underscore after subroutinenames (subroutine is Fortran-speak for “function”). So bearing in mind that BLAS is written in Fortran, to call the subroutine “dscal()” from C one must write “dscal_()”. Similarly if a C function is named “myfunc_(…)”, it may be called from Fortran using “myfunc(…)’. In addition, C passes arguments by value whereas Fortran passes arguments by reference, so to call a Fortran subroutine from C one must pass the memory address of the arguments by using the ampersand and not something like “dscal_(3, 4.323, &x[0], 1);”.
To compile we must link with the atlas libraries.
[michael@michael lin]$ gcc example.c -o example -L /usr/lib64/atlas -lf77blas [michael@michael lin]$ ./testblas 4.323000 4.323000 4.323000
With cblas.h
#include <stdio.h> #include <cblas.h> int main () { int i; double x[] = { 1, 1, 1 }; cblas_dscal(3, 4.323, x, 1); for (i = 0; i < 3; ++i) printf ("%f\n", x[i]); return 0; }
The main difference here is that instead of an “_” suffix there is a “cblas_” prefix, the cblas header has been included and that the arguments are passed by value than by reference. To compile this we link against the cblas library instead of the blas library.
[michael@michael lin]$ gcc testblasc.c -o testblas -L /usr/lib64/atlas -lcblas -latlas [michael@michael lin]$ ./testblas 4.323000 4.323000 4.323000
Compiling with C++
There are further modifications to the code if you want to write in C++ rather than C. The first is instead of “#include
extern "C" { #include <cblas.h> }
I’ve now rewritten the above example using the vectors library and making use of cpp’s input/output.
#include <cstdlib> #include <vector> #include <iostream> extern "C" { #include <cblas.h> } using namespace std; int main () { int i; vector<double> x(3,1); cblas_dscal (x.size(), 4.323, &x[0], 1); for (i = 0; i < x.size(); ++i) cout << x[i] << endl; return 0; }
The advantages of the vector class instead of a C array is that now one doesn’t need an extra variable to store the length of the array. Link against -lcblas this time than -lf77blas. All atlas libraries can be found here.