cuda vectorized实现矩阵转置

使用了共享内存和向量化传输,目前为止效果最好的一个实现

复制代码
__global__ void transposeSmemVec(float* input, float* output, const int X, const int Y){
        __shared__ float smem[32 * 4 * 32];
        unsigned int ix = 4 * (blockDim.x * blockIdx.x + threadIdx.x);
        unsigned int iy = blockDim.y * blockIdx.y + threadIdx.y;
        unsigned int ti = iy * X + ix;
        float reg[4];

        unsigned int thread_index = threadIdx.y * blockDim.x + threadIdx.x;
        unsigned int new_tx = thread_index % (blockDim.y / 4);
        unsigned int new_ty = thread_index / (blockDim.y / 4);
        unsigned int new_ix = blockIdx.y * blockDim.y + new_tx * 4;
        unsigned int new_iy = blockIdx.x * blockDim.x * 4 + new_ty;
        unsigned int to = new_iy * Y + new_ix;

        if (ix < X && iy < Y) {
                *reinterpret_cast<float4*>(&smem[(threadIdx.y * blockDim.x + threadIdx.x) * 4]) = *reinterpret_cast<float4*>(&input[ti]);
                __syncthreads();
                // *reinterpret_cast<float4*>(&reg[0]) = *reinterpret_cast<float4*>(&smem[threadIdx.y][threadIdx.x * 4]);
                // *reinterpret_cast<float4*>(&output[iy * X + ix]) = *reinterpret_cast<float4*>(&reg[0]);
                reg[0] = smem[4 * new_tx * blockDim.x * 4 + new_ty];
                reg[1] = smem[(4 * new_tx + 1) * blockDim.x * 4 + new_ty];
                reg[2] = smem[(4 * new_tx + 2) * blockDim.x * 4 + new_ty];
                reg[3] = smem[(4 * new_tx + 3) * blockDim.x * 4 + new_ty];
                // printf("---------\n");
                *reinterpret_cast<float4*>(&output[to]) = *reinterpret_cast<float4*>(&reg[0]);
        }

}
复制代码

注意在调用核函数的时候grid的x维度要缩小1/4

主函数调用核函数代码

复制代码
checkRuntime(cudaMemset(d_output, 0, sizeof(float) * X * Y));
memset(gpu_ref, 0, sizeof(float) * X * Y);
checkRuntime(cudaEventRecord(start));
dim3 grid2((X + 32 * 4 - 1) / (32 * 4), (Y + 32 - 1) / 32); transposeSmemVec<<<grid2, block>>>(d_input, d_output, X, Y);
checkRuntime(cudaEventRecord(end));
checkRuntime(cudaMemcpy(gpu_ref, d_output, sizeof(float) * X * Y, cudaMemcpyDeviceToHost));
checkRuntime(cudaEventSynchronize(end));
checkRuntime(cudaEventElapsedTime(&ms, start, end));
printf("transpose vectorialize bandwidth = %fGB/s\n", X * Y * 2 * sizeof(float) / ms / 1e6);
compareResult(cpu_ref, gpu_ref, X * Y);
复制代码

block的size在主函数最前面定义为32,注意grid和block的设置形式是(x, y, z),x在最前面,而矩阵的表示方法是(行,列)也就是(y, x),和block,grid设置是相反的

 向量化操作需要注意指令对应的线程和数据对应的线程,这两者是不一样的

posted @   Wangtn  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
历史上的今天:
2020-10-25 字符串匹配——KMP算法
2020-10-25 初识C++面向对象特性——多态
点击右上角即可分享
微信分享提示