cublasSgemm详解
来源:互联网 发布:下载种子最快的软件 编辑:程序博客网 时间:2024/05/21 07:12
cublasSgemm函数详解
cublasSgemm是CUDA的cublas库的矩阵相乘函数,由于cublas中矩阵的存储是列优先,所以cublasSgemm函数的参数容易让人误解,防止忘记,留笔记如下。
首先,在一般的C/C++程序中,我们开辟一段连续的内存,放入1,2,3,4,5,6,7,8,9,指定矩阵行和列均为3,则可表示矩阵[1,2,3 ; 4,5,6 ; 7,8,9],然而,在使用cublas时,这样表示出来的矩阵应该是[1,4,7; 2,5,8; 3,6,9]。cublas的cublasSgemm函数完成
直接看例子吧,注释中记录参数意义。
看到一个总结很不错,引用一下,:
如果前边的参数是’CUBLAS_OP_T’,那么leading dimesion 就是矩阵的列数,因为此时的矩阵是按照C语言以行优先的方式来存储的;反之如果前边的参数是’CUBLAS_OP_N’,那么leading dimesion 就是矩阵的行数,此时的矩阵保持CUBLAS的列优先存储方式。
按转置方式进行求解C=AB
// CUDA runtime 库 + CUBLAS 库#include "cuda_runtime.h"#include "cublas_v2.h"#include <iostream>#include <stdlib.h>using namespace std;// 定义测试矩阵的维度int const A_ROW = 5;int const A_COL = 6;int const B_ROW = 6;int const B_COL = 7;int main(){ // 定义状态变量 cublasStatus_t status; float *h_A,*h_B,*h_C; //存储于内存中的矩阵 h_A = (float*)malloc(sizeof(float)*A_ROW*A_COL); //在内存中开辟空间 h_B = (float*)malloc(sizeof(float)*B_ROW*B_COL); h_C = (float*)malloc(sizeof(float)*A_ROW*B_COL); // 为待运算矩阵的元素赋予 0-10 范围内的随机数 for (int i=0; i<A_ROW*A_COL; i++) { h_A[i] = (float)(rand()%10+1); } for(int i=0;i<B_ROW*B_COL; i++) { h_B[i] = (float)(rand()%10+1); } // 打印待测试的矩阵 cout << "矩阵 A :" << endl; for (int i=0; i<A_ROW*A_COL; i++){ cout << h_A[i] << " "; if ((i+1)%A_COL == 0) cout << endl; } cout << endl; cout << "矩阵 B :" << endl; for (int i=0; i<B_ROW*B_COL; i++){ cout << h_B[i] << " "; if ((i+1)%B_COL == 0) cout << endl; } cout << endl; float *d_A,*d_B,*d_C; //存储于显存中的矩阵 cudaMalloc((void**)&d_A,sizeof(float)*A_ROW*A_COL); //在显存中开辟空间 cudaMalloc((void**)&d_B,sizeof(float)*B_ROW*B_COL); cudaMalloc((void**)&d_C,sizeof(float)*A_ROW*B_COL); cublasHandle_t handle; cublasCreate(&handle); cudaMemcpy(d_A,h_A,sizeof(float)*A_ROW*A_COL,cudaMemcpyHostToDevice); //数据从内存拷贝到显存 cudaMemcpy(d_B,h_B,sizeof(float)*B_ROW*B_COL,cudaMemcpyHostToDevice); float a = 1, b = 0; cublasSgemm( handle, CUBLAS_OP_T, //矩阵A的属性参数,转置,按行优先 CUBLAS_OP_T, //矩阵B的属性参数,转置,按行优先 A_ROW, //矩阵A、C的行数 B_COL, //矩阵B、C的列数 A_COL, //A的列数,B的行数,此处也可为B_ROW,一样的 &a, //alpha的值 d_A, //左矩阵,为A A_COL, //A的leading dimension,此时选择转置,按行优先,则leading dimension为A的列数 d_B, //右矩阵,为B B_COL, //B的leading dimension,此时选择转置,按行优先,则leading dimension为B的列数 &b, //beta的值 d_C, //结果矩阵C A_ROW //C的leading dimension,C矩阵一定按列优先,则leading dimension为C的行数 ); //此时得到的结果便是C=AB,但由于C是按列优先,故此时得到的C应该是正确结果的转置 std::cout << "计算结果的转置 ( (A*B)的转置 ):" << std::endl; cudaMemcpy(h_C,d_C,sizeof(float)*A_ROW*B_COL,cudaMemcpyDeviceToHost); for(int i=0;i<A_ROW*B_COL;++i) { std::cout<<h_C[i]<<" "; if((i+1)%B_COL==0) std::cout<<std::endl; } cudaFree(d_A); cudaFree(d_B); cudaFree(d_C); free(h_A); free(h_B); free(h_C); return 0;}
不按转置方式直接求解
前一种方法求得的C是正确结果的转置,那么我们可以直接求
// CUDA runtime 库 + CUBLAS 库#include "cuda_runtime.h"#include "cublas_v2.h"#include <iostream>#include <stdlib.h>using namespace std;// 定义测试矩阵的维度int const A_ROW = 5;int const A_COL = 6;int const B_ROW = 6;int const B_COL = 7;int main(){ // 定义状态变量 cublasStatus_t status; float *h_A,*h_B,*h_C; //存储于内存中的矩阵 h_A = (float*)malloc(sizeof(float)*A_ROW*A_COL); //在内存中开辟空间 h_B = (float*)malloc(sizeof(float)*B_ROW*B_COL); h_C = (float*)malloc(sizeof(float)*A_ROW*B_COL); // 为待运算矩阵的元素赋予 0-10 范围内的随机数 for (int i=0; i<A_ROW*A_COL; i++) { h_A[i] = (float)(rand()%10+1); } for(int i=0;i<B_ROW*B_COL; i++) { h_B[i] = (float)(rand()%10+1); } // 打印待测试的矩阵 cout << "矩阵 A :" << endl; for (int i=0; i<A_ROW*A_COL; i++){ cout << h_A[i] << " "; if ((i+1)%A_COL == 0) cout << endl; } cout << endl; cout << "矩阵 B :" << endl; for (int i=0; i<B_ROW*B_COL; i++){ cout << h_B[i] << " "; if ((i+1)%B_COL == 0) cout << endl; } cout << endl; float *d_A,*d_B,*d_C; //存储于显存中的矩阵 cudaMalloc((void**)&d_A,sizeof(float)*A_ROW*A_COL); //在显存中开辟空间 cudaMalloc((void**)&d_B,sizeof(float)*B_ROW*B_COL); cudaMalloc((void**)&d_C,sizeof(float)*A_ROW*B_COL); cublasHandle_t handle; cublasCreate(&handle); cudaMemcpy(d_A,h_A,sizeof(float)*A_ROW*A_COL,cudaMemcpyHostToDevice); //数据从内存拷贝到显存 cudaMemcpy(d_B,h_B,sizeof(float)*B_ROW*B_COL,cudaMemcpyHostToDevice); float a = 1, b = 0; cublasSgemm( handle, CUBLAS_OP_N, //矩阵A的属性参数,不转置,按列优先 CUBLAS_OP_N, //矩阵B的属性参数,不转置,按列优先 B_COL, //矩阵B^T、C^T的行数 A_ROW, //矩阵A^T、C^T的列数 B_ROW, //B^T的列数,A^T的行数,此处也可为A_COL,一样的 &a, //alpha的值 d_B, //左矩阵,为B^T B_COL, //B^T的leading dimension,按列优先,则leading dimension为B^T的行数(B的列数) d_A, //右矩阵,为A^T A_COL, //A^T的leading dimension,按列优先,则leading dimension为A^T的行数(A的列数) &b, //beta的值 d_C, //结果矩阵C B_COL //C^T的leading dimension,C^T矩阵一定按列优先,则leading dimension为C^T的行数(C的列数) ); //此时得到的结果便是C=AB,但由于C是按列优先,故此时得到的C应该是正确结果的转置 std::cout << "计算结果的转置 ( (A*B)的转置 ):" << std::endl; cudaMemcpy(h_C,d_C,sizeof(float)*A_ROW*B_COL,cudaMemcpyDeviceToHost); for(int i=0;i<A_ROW*B_COL;++i) { std::cout<<h_C[i]<<" "; if((i+1)%B_COL==0) std::cout<<std::endl; } cudaFree(d_A); cudaFree(d_B); cudaFree(d_C); free(h_A); free(h_B); free(h_C); return 0;}
- cublasSgemm详解
- cublasSgemm函数
- cublasSgemm实现矩阵的相乘
- cublasSgemm实现矩阵的相乘
- cublasSgemm和cublasDgemm的比较
- cublasSgemm函数实现矩阵乘
- cuda 矩阵乘法函数之cublasSgemm
- cublasSgemm处理C中按行存储的矩阵乘法
- 详解
- 详解
- 详解
- 详解
- &,&&,|,||详解
- 详解
- Scala详解--------基础知识详解
- Spring详解-----------事务详解
- github 详解详解
- InputFilter详解、TextWatcher详解
- 【首日直击•AWE•2016】云天环保 低成本网格化环境空气监测微站 大放异彩
- 腾讯众创空间亮相西安 欲打造西北部创业旗舰
- 魔品科技:创业寒冬,解决刚需才是王道
- 创业不必再奔波 腾讯众创空间11日解答西安创业者百问
- “期货”玩法,英特尔也学会了
- cublasSgemm详解
- ps抠图的两种方式[杂]
- 家谱处理(30 分)
- 用于机器学习的分类算法
- 中国版Alphago,是否又只是一个“民科”的故事而已?
- 互联在线:O2O创业潮后,中小企业的互联网化依然势不可挡
- 9大医生集团入驻腾讯腾爱医生 探索互联网+医疗
- 黑客“世界杯”Pwn2Own 2016四大看点
- 双曲面屏+全金属的魅力 快无边界Xplay5全面解析图赏