Skip to content

Instantly share code, notes, and snippets.

@caiorss
Created July 6, 2018 20:29
Show Gist options
  • Save caiorss/7e97239e9d1ba60a73724aed7d9ed5a4 to your computer and use it in GitHub Desktop.
Save caiorss/7e97239e9d1ba60a73724aed7d9ed5a4 to your computer and use it in GitHub Desktop.
Callign Lapack and Blas fortran libraries from C++11
#include <iostream>
#include <iomanip>
#include <vector>
#include <chrono>
// External linkage without header file goes here.
// The symbols here are defined in *.o (Object files)
// or shared libraries. (*.so - UNIX) or (*.dll - Windows)
extern "C" {
// WARNING: This is the GFortran ABI which encodes symbols with underscore (_)
// at the end. It may be necessary to use #ifdef contional compilation to
// abstract other compiler's ABIs.
void daxpy_(int* n, double* alpha,
double* x, int *incx,
double* y, int* incy
);
}
void tableHead(const std::vector<std::vector<double>>& columns, int n = 5){
int ncols = columns.size();
for(int i = 0; i < n; i++){
std::cout << std::setw(10) << i;
for(int j = 0; j < ncols; j++ ){
std::cout << std::setw(10) << std::fixed << std::setprecision(3) << columns[j][i];
}
std::cout << std::endl;
}
}
void tableTail(const std::vector<std::vector<double>>& columns, int n = 5){
int ncols = columns.size();
// Assume that the table has at least one column
int columnSize = columns.at(0).size();
int tailSize = n <= columnSize ? n : columnSize;
for(int i = columnSize - tailSize; i < columnSize; i++){
std::cout << std::setw(15) << i;
for(int j = 0; j < ncols; j++ ){
std::cout << std::setw(15) << std::fixed << std::setprecision(3) << columns[j][i];
}
std::cout << std::endl;
}
}
int main(){
using std::cout;
using std::endl;
const int N = 1000000;
cout << "Number of vector elements N = " << N << endl;
std::vector<double> X;
std::vector<double> Y;
for (int i = 0; i < N; i++){
// cout << "i = " << i << endl;
X.push_back(i);
Y.push_back(4 * i);
}
double a = 0.2;
int incx = 1;
int incy = 1;
int n = N;
cout << "Vector X size " << X.size() << " - Vector Y size = " << Y.size() << endl;
cout << "Vectors X and Y before operation: daxpy" << endl;
tableHead({X, Y});
// Blas Level Subroutine - vector to vector operations
// Operation: Y <- a.X + Y
// Computes : Y <- 0.2 * X + Y
auto start = std::chrono::system_clock::now();
daxpy_(&n, &a, X.data(), &incx, Y.data(), &incy);
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_time = end - start;
cout << "[Head] Vectors X and Y after operation: daxpy" << endl;
tableHead({X, Y});
cout << "[Tail] Vectors X and Y after operation: daxpy" << endl;
tableTail({X, Y});
cout << "Finish execution - elapsed time in milliseconds = "
<< 1000.0 * elapsed_time.count()
<< endl;
return 0;
}

Note: The only way to know the name mangling schema is by checking the symbols exported by the lapack and blas shared library.

$ nm -D /usr/lib64/liblapack.so.3.6.1 | head -n 20
                 U atan2
                 U atan2f
00000000007faa70 B __bss_start
                 U cabs
                 U cabsf
                 U caxpy_
0000000000396390 T cbbcsd_
0000000000261390 T cbdsqr_
                 U ccopy_
                 U cdotc_
                 U cdotu_

 ... ... ... ... ... ... ... ... 

$ nm -D /usr/lib64/liblapack.so.3.6.1 | tail -n 5
00000000004d96e0 T zunmrq_
00000000004d9f60 T zunmrz_
00000000004da930 T zunmtr_
00000000004db010 T zupgtr_
00000000004db460 T zupmtr_

# The function daxpy - has its symbol encoded as daxpy_ 
# This assumption that Fortran functions ends with name + (_) underline 
# can only be guaranteed for libraries compiled with GNU Fortran compiler.
$ nm -D /usr/lib64/liblapack.so.3.6.1 | grep -i daxpy
                 U daxpy_
$ clang++ blasLapack1.cpp -std=c++11 -g -o out.bin -Wall -Wextra -llapack -lblas -lm && ./out.bin
Number of vector elements N = 1000000
Vector X size 1000000 - Vector Y size = 1000000
Vectors X and Y before operation: daxpy
0 0.000 0.000
1 1.000 4.000
2 2.000 8.000
3 3.000 12.000
4 4.000 16.000
[Head] Vectors X and Y after operation: daxpy
0 0.000 0.000
1 1.000 4.200
2 2.000 8.400
3 3.000 12.600
4 4.000 16.800
[Tail] Vectors X and Y after operation: daxpy
999995 999995.000 4199979.000
999996 999996.000 4199983.200
999997 999997.000 4199987.400
999998 999998.000 4199991.600
999999 999999.000 4199995.800
Finish execution - elapsed time in milliseconds = 1.189
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment