OpenBLAS 的编译运行可参考:https://github.com/xianyi/OpenBLAS/blob/develop/USAGE.md
该部分转自:https://blog.csdn.net/cocoonyang/article/details/63068108
Level 1 函数处理单一向量的线性运算以及两个向量的二元运算。
接口函数名称由前缀+操作简称组成。
例如:SROTG,其中:
S -- 标明矩阵或向量中元素数据类型的前缀;
ROTG -- 向量运算简称。
Level 2 函数处理 矩阵与向量的运算,同时也包含线性方程求解计算。
Level 3 函数包含矩阵与矩阵运算。
接口函数名称由前缀 + 矩阵类型 + 操作简称组成。
例如: SGEMV,其中:
S -- 标明矩阵或向量中元素数据类型的前缀;
GE -- 矩阵类型
MV -- 向量或矩阵运算简称
GE - GEnearl 稠密矩阵
GB - General Band 带状矩阵
SY - SYmmetric 对称矩阵
SB - Symmetric Band 对称带状矩阵
SP - Symmetric Packed 压缩存储对称矩阵
HE - HEmmitian Hemmitian矩阵,自共轭矩阵
HB - Hemmitian Band 带状Hemmitian矩阵
HP - Hemmitian Packed 压缩存储Hemmitian矩阵
TR - TRiangular 三角矩阵
TB - Triangular Band 三角带状矩阵
TP - Triangular Packed 压缩存储三角矩阵
以下为 openblas 中双精度稠密矩阵向量乘函数,计算式为 y=alpha*A*x+beta*y。
void cblas_sgemv(
OPENBLAS_CONST enum CBLAS_ORDER order, //CblasRowMajor或者CblasColMajor(行主序或列主序,默认为行)
OPENBLAS_CONST enum CBLAS_TRANSPOSE trans, //CblasNoTrans或者CblasTrans(矩阵不转置或者转置,需要时会自动转置)
OPENBLAS_CONST blasint m, //矩阵行数
OPENBLAS_CONST blasint n, //矩阵的列数
OPENBLAS_CONST float alpha, //y=alpha*A*x+beta*y中的alpha
OPENBLAS_CONST float *a, //A矩阵的缓冲区首地址
OPENBLAS_CONST blasint lda, //A矩阵的列数
OPENBLAS_CONST float *x, //x向量的缓冲区首地址
OPENBLAS_CONST blasint incx, //x里面每次跳跃累加的个数,默认为1
OPENBLAS_CONST float beta, //y=alpha*A*x+beta*y中的beta
float *y, //y的缓冲区首地址
OPENBLAS_CONST blasint incy //y里面每次跳跃累加的个数,默认为1
)
我是在 Linux 下编译运行的,需要自己链接,过程如下:
gcc ./dgemv_test.c -I/opt/software/libopenblas/include -L/opt/software/libopenblas/lib -o ./dgemv_test.out -lopenblas -lpthread
(多线程需要链接到pthread)
其中:-I(大写i)后面为 OpenBLAS 所需头文件 <cblas.h> 所在的目录;-L后面为 OpenBLAS 的库文件所在的目录。
在环境变量中设置线程数为n(自己取值,取1为单线程):
export OPENBLAS_NUM_THREADS=4(已确认可行)。
./dgemv_test.out
注:该网站(https://github.com/xianyi/OpenBLAS/blob/develop/USAGE.md)给出了另外两种单线程方法,推测同理可设置多线程,但是没有继续尝试。
可以将23步改成:
a. make USE_THREAD=4(4自己设置线程数,取0为单线程)
b. ./dgemv_test.out openblas_set_num_threads2(2自己设置线程数,取1为单线程)
附上自己测试时候的代码。
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <cblas.h>
#include <sys/time.h>
#define BUF_SIZE (1024)
char buf[BUF_SIZE];
int main(int argc, char** argv) {
//读取矩阵数据
long long n, m, num_items,indx;
int row, col;
double val;
bool flag = false;
double *matrix;
FILE* fd = fopen(argv[1], "r");
while (fgets(buf, BUF_SIZE, fd)) {
if (buf[0] == '%') continue;
if (flag) {
sscanf(buf, "%d %d %le", &row, &col, &val);
indx = (row-1)*m+(col-1);
matrix[indx] = val;
}
else {
sscanf(buf, "%lld %lld %lld", &n, &m, &num_items);
long long nm = n * m * sizeof(double);
matrix = (double*)malloc(nm);
flag = true;
}
}
fclose(fd);
flag = false;
//读取向量
double *vect_x;
long long i = 0;
long long v_n,v_n_size;
//FILE* fc = fopen(file_vect,"r");
FILE* fc = fopen(argv[2],"r");
while (fgets(buf, BUF_SIZE, fc)) {
if (buf[0] == '%') continue;
if (flag) {
sscanf(buf, "%le", &val);
vect_x[i++] = val;
}
else {
sscanf(buf, "%lld", &v_n);
v_n_size = v_n * sizeof(double);
vect_x = (double*)malloc(v_n_size);
flag = true;
}
}
fclose(fc);
//clock()测量你的进程使用的CPU时间,而不是挂钟时间。当你有多个线程同时运行时,你显然可以更快地消耗CPU时间。
//计算时间——开始
struct timeval start_t,end_t;
double *y = (double*)malloc(v_n_size);
int j=0;
gettimeofday(&start_t, NULL);
//openblas函数计算
for(j=0;j<10;j++){
//矩阵数据行列
cblas_dgemv(CblasRowMajor, CblasNoTrans, n, m, 1, matrix, m, vect_x, 1, 0, y, 1);
//矩阵数据列行
//cblas_dgemv(CblasRowMajor, CblasTrans, n, m, 1, matrix, m, vect_x, 1, 0, y, 1);
}
//计算时间——结束
gettimeofday(&end_t, NULL);
//计算时间——过程(结束-开始)
double total_t_sec, total_t_usec, total_t;
total_t_sec = (double)(end_t.tv_sec - start_t.tv_sec);
total_t_usec = (double)(end_t.tv_usec - start_t.tv_usec);
total_t = total_t_sec + total_t_usec / 1000000.0;
printf("Time spent : %f seconds\n", total_t);
return 0;
}