最近发现了一条真理,那就是科研项目中遇到问题,千万别企图绕过去,因为,最终还是会发现,那个悬而未决的问题会最终把你带回原地。废话不多说,先盗用大佬的一张图,在CUDA架构下, 显示芯片执行时的最小单位是thread. 数个thread可以组成一个block. 一个block中的thread能存取同一块共享的内存(shared memory), 而且可以快速进行同步的动作, 特别要注意, 这是块(block)同步. 不同block中的thread无法存取同一个共享的内存, 因此无法直接互通或进行同步. 因此, 不同block中的thread能合作的程度是比较低的)然后依据thread, block和grid, 有着不同的存储. 核心就是thread. 可以结合下图进行理解:
它的理念是把矩阵分成小块,一个线程计算出的Csub就是对应一个元素,然后你想象所有线程是并行的,所以所有的元素计算就可以理解过来了,但是单纯的一个线程是解决不了这个问题的,因为它小循环迭代的时候是需要所有元素的内容的,这也是使用__syncthreads()的作用,而你在使用global memory的时候,不需要用这个,因为每个线程各做各的,都需要去读global memory,这也是使用shared memory的作用,它可以减少对global 的访问。
CPU上矩阵乘法代码,在GPU中,核函数的的ID操作方式也是基于这样的循环去操作线程ID的,从而有助于矩阵乘法在GPU中并行执行。根据之前的矩阵乘法实验结果来看,矩阵数目越大,发而能把GPU的优良性能发挥出来,随着矩阵数量的增多,时间的减少也是一个量级一个量级的减少。两个1000×1000的矩阵相称,时间是0.221341,两个100000×100000的矩阵相称,时间是0.000025,这个结果很惊讶了。1000000×1000000时间是0.160396,
/* CPUMatMultiply:CPU下矩阵乘法
* a:第一个矩阵指针,表示a[M][N]
* b:第二个矩阵指针,表示b[N][S]
* result:结果矩阵,表示为result[M][S]
*/
#include <iostream>
using namespace std;
void CPUMatMultiply(int M, int N, int S, float* a, float* b, float* c)
{
for (int Row = 0; Row < M; ++ Row)
for (int Col = 0; Col < N; ++ Col )
{
float sum = 0;
for (int i = 0; i < N; ++i)
{
float A = a[Row * N + i];
float B = b[Col + i * S];
sum += A * B;
}
c[Row* S + Col] = sum;
}
}
int main()
{
//这里将矩阵按照行优先转换成了一维的形式
float a[6] = {
11.4, 24, 33.5, 45, 55 ,32.4 }; //2×3的矩阵
float b[12] = {
12,43,22.4, 31.3, 12,324,23,12, 44.4,23.4,65.3,73};//3×4的矩阵
float c[8] = {
0 }; //2×4的结果矩阵
int M=2,N=3,S=4;
//上面两个矩阵比较简单,但是我实际上需要操作的矩阵是很多的, a矩阵大约是3×3的矩阵,而b矩阵大到3×100000,所以目前我的问题是如何将这样大的矩阵赋值给指针a,b,c.
MatrixMulOnHost(M