cuda编程入门(3)—— 实现矩阵乘法(一)

网友投稿 1433 2022-11-23

cuda编程入门(3)—— 实现矩阵乘法(一)

cuda编程入门(3)—— 实现矩阵乘法(一)

文章目录

​​一、CPU下的一般矩阵乘法​​​​二、CPU下循环交换矩阵乘法​​​​三、CPU下转置矩阵乘法​​

​​附录(连续访问为什么比随机访问快)​​

本文章为 ​​《 GPU编程与优化 大众高性能计算》​​ 的读书笔记,例子也都取自书中教程。

一、CPU下的一般矩阵乘法

// 矩阵乘法一// m*l l*nvoid matrix_mul(float* x, float * y, float* z, int m, int n, int l){ for(int i = 0; i < m; i++) { for(int j = 0; j < n; j++) { for(int k = 0; k < l; k++) { z[i*n+ j] += x[i*l + k] * y[k*n + j]; } } }}#include #include #include int main(){ int M = 2048; int L = 1024; int N = 512; // 申请host内存 float *x = NULL; float *y = NULL; float *z = NULL; x = (float*)malloc(M*L*sizeof(float)); y = (float*)malloc(L*N*sizeof(float)); z = (float*)malloc(M*N*sizeof(float)); if(x == NULL || y == NULL || z == NULL) return 0; // 初始化数据 for (int i = 0; i < M; ++i) { for (int j = 0; j < L; ++j) { x[i*L + j] = 1.1; } } for (int i = 0; i < L; ++i) { for (int j = 0; j < N; ++j) { y[i*N + j] = 1.1; } } for (int i = 0; i < M; ++i) { for (int j = 0; j < N; ++j) { z[i*N + j] = 0; } } // 执行矩阵乘法 using namespace std::chrono; steady_clock::time_point t1 = steady_clock::now(); matrix_mul(x, y, z, M, N, L); steady_clock::time_point t2 = steady_clock::now(); duration time_span = duration_cast>(t2 - t1); std::cout << "It took me " << time_span.count() << " seconds."; std::cout << std::endl; // 输出前10个数值 for(int i = 0; i < 10; i++) { std::cout << z[i] << " "; } std::cout << std::endl; std::cout << "Done!" << std::endl; // 释放host内存 free(x); free(y); free(z); return 0;}

matrix_mul函数中 对矩阵 y 的数据访问是不连续的,会影响速度。

二、CPU下循环交换矩阵乘法

// 矩阵乘法一// m*l l*nvoid matrix_mul(float* x, float * y, float* z, int m, int n, int l){ for(int i = 0; i < m; i++) { for(int k = 0; k < l; k++) { for(int j = 0; j < n; j++) { z[i*n + j] += x[i*l + k] * y[k*n + j]; } } }}#include #include #include int main(){ int M = 2048; int L = 1024; int N = 512; // 申请host内存 float *x = NULL; float *y = NULL; float *z = NULL; x = (float*)malloc(M*L*sizeof(float)); y = (float*)malloc(L*N*sizeof(float)); z = (float*)malloc(M*N*sizeof(float)); if(x == NULL || y == NULL || z == NULL) return 0; // 初始化数据 for (int i = 0; i < M; ++i) { for (int j = 0; j < L; ++j) { x[i*L + j] = 1.1; } } for (int i = 0; i < L; ++i) { for (int j = 0; j < N; ++j) { y[i*N + j] = 1.1; } } for (int i = 0; i < M; ++i) { for (int j = 0; j < N; ++j) { z[i*N + j] = 0; } } // 执行矩阵乘法 using namespace std::chrono; steady_clock::time_point t1 = steady_clock::now(); matrix_mul(x, y, z, M, N, L); steady_clock::time_point t2 = steady_clock::now(); duration time_span = duration_cast>(t2 - t1); std::cout << "It took me " << time_span.count() << " seconds."; std::cout << std::endl; // 输出前10个数值 for(int i = 0; i < 10; i++) { std::cout << z[i] << " "; } std::cout << std::endl; std::cout << "Done!" << std::endl; // 释放host内存 free(x); free(y); free(z); return 0;}

三、CPU下转置矩阵乘法

// 矩阵乘法一// m*l l*n#include void matrix_mul(float* x, float * y, float* z, int m, int n, int l){ float* transposed = (float*)malloc(l*n*sizeof(float)); // l*n --> n*l for(int i = 0; i < n; i++) { for(int j = 0; j < l; j++) { transposed[i*l + j] = y[j*n + i]; } } //m*l n*l for(int i = 0; i < m; i++) { for(int j = 0; j < n; j++) { for(int k = 0; k < l; k++) { z[i*n + j] += x[i*l + k] * y[j*l + k]; } } } free(transposed);}#include #include #include int main(){ int M = 2048; int L = 1024; int N = 512; // 申请host内存 float *x = NULL; float *y = NULL; float *z = NULL; x = (float*)malloc(M*L*sizeof(float)); y = (float*)malloc(L*N*sizeof(float)); z = (float*)malloc(M*N*sizeof(float)); if(x == NULL || y == NULL || z == NULL) return 0; // 初始化数据 for (int i = 0; i < M; ++i) { for (int j = 0; j < L; ++j) { x[i*L + j] = 1.1; } } for (int i = 0; i < L; ++i) { for (int j = 0; j < N; ++j) { y[i*N + j] = 1.1; } } for (int i = 0; i < M; ++i) { for (int j = 0; j < N; ++j) { z[i*N + j] = 0; } } // 执行矩阵乘法 using namespace std::chrono; steady_clock::time_point t1 = steady_clock::now(); matrix_mul(x, y, z, M, N, L); steady_clock::time_point t2 = steady_clock::now(); duration time_span = duration_cast>(t2 - t1); std::cout << "It took me " << time_span.count() << " seconds."; std::cout << std::endl; // 输出前10个数值 for(int i = 0; i < 10; i++) { std::cout << z[i] << " "; } std::cout << std::endl; std::cout << "Done!" << std::endl; // 释放host内存 free(x); free(y); free(z); return 0;}

附录(连续访问为什么比随机访问快)

​​内存(DRAM)的连续读写速度和随机读写速度是一样的吗?​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:cuda编程入门(2)—— 浅谈核函数
下一篇:LeetCode——138. 复制带随机指针的链表(借用map实现复制)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~