使用共享内存和全局内存测试cuda矩阵乘法的结果

使用共享内存和全局内存测试cuda矩阵乘法的结果,cuda,Cuda,我一直在研究cuda 在CUDA编程指南中,共享内存访问时间快于全局内存时间 所以,我编写了执行矩阵乘法的代码 这是我的密码。版本1使用全局内存,版本2使用共享内存 我的gpu是特斯拉c2070 cuda sdk版本4.2 主代码 #define Matrix_Width 9216 #define Matrix_Divide 4 #define Tile_Width 32 #define Ce_Size 4096 #if Matrix_Width == 9216 #de

我一直在研究cuda

在CUDA编程指南中,共享内存访问时间快于全局内存时间

所以,我编写了执行矩阵乘法的代码

这是我的密码。版本1使用全局内存,版本2使用共享内存

我的gpu是特斯拉c2070 cuda sdk版本4.2


主代码

#define Matrix_Width   9216
#define Matrix_Divide  4
#define Tile_Width     32
#define Ce_Size 4096

#if Matrix_Width == 9216
    #define Matrix_Size 9216*9216
#elif Matrix_Width == 12800
    #define Matrix_Size 12800*12800
#elif Matrix_Width == 15872
    #define Matrix_Size 15872*15872
#elif Matrix_Width == 18432
    #define Matrix_Size 18432*18432
#endif

float* H_Input1 = (float*)malloc( sizeof(float) * Matrix_Size );
float* H_Input2 = (float*)malloc( sizeof(float) * Matrix_Size );
float* H_Output = (float*)malloc( sizeof(float) * Matrix_Size );

for( int i=0 ; i < Matrix_Size ; i++ ){
    H_Input1[i] = 1.0f;
H_Input2[i] = 1.0f;
}
memset( H_Output, 0 , sizeof(float) * Matrix_Size );

float* D_Input1;
float* D_Input2;
float* D_Output;

cudaMalloc( (void**)&D_Input1, sizeof(float) * Matrix_Size );
cudaMalloc( (void**)&D_Input2, sizeof(float) * Matrix_Size );
cudaMalloc( (void**)&D_Output, sizeof(float) * Matrix_Size );
cudaMemcpy( D_Input1, H_Input1, sizeof(float) * Matrix_Size, cudaMemcpyHostToDevice );
cudaMemcpy( D_Input2, H_Input2, sizeof(float) * Matrix_Size, cudaMemcpyHostToDevice );
cudaMemcpy( D_Output, H_Output, sizeof(float) * Matrix_Size, cudaMemcpyHostToDevice );


event_pair Event;
start_timer( &Event );
dim3  dimGrid( Matrix_Width/Matrix_Divide/Tile_Width, Matrix_Width/Matrix_Divide/Tile_Width, 1 );
dim3 dimBlock( Tile_Width, Tile_Width, 1 );

kernel_global<< dimGrid, dimBlock>>>( D_Input1, D_Input2, D_Output );
stop_timer( &Event, "1GB mMemory Test\n" );
cudaMemcpy( H_Output, D_Output, sizeof(float) * Matrix_Size, cudaMemcpyDeviceToHost );
#定义矩阵_宽度9216
#定义矩阵_除以4
#定义平铺宽度32
#定义Ce_尺寸4096
#如果矩阵_宽度==9216
#定义矩阵_大小9216*9216
#elif矩阵_宽度==12800
#定义矩阵_大小12800*12800
#elif矩阵_宽度==15872
#定义矩阵_大小15872*15872
#elif矩阵_宽度==18432
#定义矩阵_大小18432*18432
#恩迪夫
float*H_Input1=(float*)malloc(sizeof(float)*矩阵大小);
float*H_Input2=(float*)malloc(sizeof(float)*矩阵大小);
float*H_输出=(float*)malloc(sizeof(float)*矩阵_大小);
对于(int i=0;i>(D\u输入1、D\u输入2、D\u输出);
停止计时器(&事件,“1GB内存测试”\n);
cudaMemcpy(H_输出,D_输出,sizeof(float)*矩阵大小,cudamemcpydevicetoost);

内核版本1
\uuuuu全局\uuuuu无效内核\u全局(浮点*Input1,浮点*Input2,浮点*Output){
对于(int i=0;i

内核版本2
\uuuuu全局\uuuuu无效内核\u共享(浮点*Input1,浮点*Input2,浮点*Output){
__共享浮点输入1_s[平铺宽度][平铺宽度];
__共享浮点输入2_s[平铺宽度][平铺宽度];
int Bx=blockIdx.x;
int By=blockIdx.y;
int Tx=线程idx.x;
int Ty=threadIdx.y;
对于(int i=0;i

此代码生成宽度为9216的矩阵

它不能一次计算。因为块的最大计数为65535,线程数为1024

所以我用4来划分矩阵宽度,所以矩阵被划分为16个块

一次可以计算1个区块

所以我使用了loopcount为16的循环(i*j=16)

块被分为块和线程。。(瓷砖宽度=32)

测试结果真奇怪

第1版花了90秒

第二版花了130秒

我不能理解这个结果

我认为共享内存元素恢复在平铺中

为什么版本1比版本2快


致以最良好的祝愿

特斯拉C2070是一款计算能力2.0设备,可缓存全局内存访问。因此,在这两种情况下,内环都在片上存储器中运行(第一次迭代除外)

唯一的区别是,在第二个版本中,将数据加载到共享内存的附加代码需要额外的时间,而在第一个版本中,这项工作是通过缓存逻辑在硬件中完成的


只有在compute capability 1.x设备上,或者如果您比硬件缓存的LRU(最近使用最少的)逻辑更好地了解哪些数据被重用,才值得在共享内存中手动缓存数据。

特斯拉C2070是一款计算能力2.0设备,用于缓存全局内存访问。因此,在这两种情况下,内环都在片上存储器中运行(第一次迭代除外)

唯一的区别是,在第二个版本中,将数据加载到共享内存的附加代码需要额外的时间,而在第一个版本中,这项工作是通过缓存逻辑在硬件中完成的


只有在compute capability 1.x设备上,或者如果您比硬件缓存的LRU(最近使用最少的)逻辑更好地了解哪些数据被重用,才值得在共享内存中手动缓存数据。

什么是CUDA版本?你的GPU是什么?我的GPU是特斯拉c2070 sdk版本是4.2什么是CUDA版本?你的GPU是什么?我的GPU是特斯拉c2070 sdk版本是4.2很好的答案。共享内存的延迟约为100个周期(费米)。根据结果,看起来L2和共享内存的延迟顺序相同。在这样的体系结构下,使用共享内存进行此操作并不是最糟糕的
__global__ void kernel_global( float* Input1, float* Input2, float* Output ){

for( int i = 0 ; i < Matrix_Divide ; i++ ){
for( int j = 0 ; j < Matrix_Divide ; j++ ){

float Sum = 0;
int Row = (i * (Matrix_Width/Matrix_Divide)) + (blockIdx.y * Tile_Width) + threadIdx.y; 
int Col = (j * (Matrix_Width/Matrix_Divide)) + (blockIdx.x * Tile_Width) + threadIdx.x;

    for( int k = 0 ; k < Matrix_Width ; k++ ){
        Sum += Input1[ Row * Matrix_Width + k ] * Input2[ k * Matrix_Width + Col ];
    }
    Output[ Row*Matrix_Width+Col] = Sum;
    }
    }
}
    __global__ void kernel_shared( float* Input1, float* Input2, float* Output ){

    __shared__ float Input1_s[Tile_Width][Tile_Width];
    __shared__ float Input2_s[Tile_Width][Tile_Width];

    int Bx = blockIdx.x;
    int By = blockIdx.y;
    int Tx = threadIdx.x;
    int Ty = threadIdx.y;

    for( int i = 0 ; i < Matrix_Divide ; i++ ){
        for( int j = 0 ; j < Matrix_Divide ; j++ ){

            float Sum = 0;
            int Row = (i * (Matrix_Width/Matrix_Divide)) + (By * Tile_Width) + Ty;
            int Col = (j * (Matrix_Width/Matrix_Divide)) + (Bx * Tile_Width) + Tx;


            for( int m = 0 ; m < Matrix_Width/Tile_Width ; m++ ){

                Input1_s[Ty][Tx] = Input1[ Row * Matrix_Width + ( m * Tile_Width + Tx ) ];
                Input2_s[Ty][Tx] = Input2[ ( m * Tile_Width + Ty ) * Matrix_Width + Col ];
                __syncthreads();


                for( int k = 0 ; k < Tile_Width; k++ ){
                    Sum += Input1_s[Ty][k] * Input2_s[k][Tx];
                }
                __syncthreads();
            }
            Output[ Row*Matrix_Width+Col] = Sum;
        }
    }
}