How to use cublasSgemm() ?

一. 数据的存储方式

对于一个矩阵,在内存中有两种存储顺序:(下面图和表格摘自 https://en.wikipedia.org/wiki/Row-major_order)

对于下面的矩阵:

可以有两种存储方式:左为列优先,右为行优先。


顾名思义,列优先:优先按列存储,先存完第一列再存第二列,行优先同理。

C/C++中矩阵的存储为行优先,但cublas/Matlab中是列优先准则,在不同语言间读取数据时需要注意这点,同时在写Matlab时要尽量取一个二维数组的列,而不是行。

扩展到N维矩阵,列优先意味着存储时第一个维度先变化,即存储顺序为(0,0,0,...)、(1,0,0,...)、(max,0,0,...)、(0,1,0,...)、(1,1,0,...),

行优先意味着最后一个维度先变化。

p.s:在处理数据时,说明数据的顺序需要表明:

        1)维度安排 

        2)是否是行\列优先

这两个信息缺一不可。

p.s:caffe的Blobnumpy的arrayOpenCV的Mat都是和C语言一样,是行优先的。

p.s:貌似只有CUBLAS/Matlab中的矩阵是列优先,Eigen默认使用列优先存储,可以指定存储方式。

二. cublasSgemm的使用

在做人脸相似度比对时,需要求解人脸特征与注册人脸特征的余弦相似度。当注册人连库的规模达到百万千万的规模是该过程是很耗时的,我们可以采用GPU进行优化计算。优化策略如下:

     1. 多batch

     2. 利用cublasgemm加速计算

假设一个batch的三个人脸特征如A矩阵所述,人脸注册库特征如B所描述:

目标求解:


转化为:

                                                          d=norm(A).norm(B)

矩阵norm(A):

矩阵norm(B):


由于cublas按照列优先存储,那么数据放到cublas内,如果我们再次按照按行优先取出来,那么我们会以为cublas对矩阵做了“转置”运算。

我们来看看caffe是怎么封装的:

推荐阅读更多精彩内容