cuda算子--矩阵转置

复制代码
#include <cuda_runtime.h>

#define TILE 32
#define BLOCK_ROWS 8   // block 的 y 方向线程数,配合 TILE 减少 padding 浪费

// 用 padding 避免 shared bank conflict
__global__ void transpose_shared_kernel(const float* __restrict__ input,
                                        float* __restrict__ output,
                                        int rows, int cols) {
    __shared__ float tile[TILE][TILE + 1];

    const int tx = threadIdx.x;   // [0, TILE)
    const int ty = threadIdx.y;   // [0, BLOCK_ROWS)

    // ---- 读阶段 ----
    // 该 block 负责 input 的子块:
    //   行 [blockIdx.y*TILE, blockIdx.y*TILE + TILE)
    //   列 [blockIdx.x*TILE, blockIdx.x*TILE + TILE)
    const int col = blockIdx.x * TILE + tx;   // input 列
    const int row = blockIdx.y * TILE + ty;   // input 行起点

    #pragma unroll
    for (int j = 0; j < TILE; j += BLOCK_ROWS) {
        if (col < cols && (row + j) < rows)
            tile[ty + j][tx] = input[(size_t)(row + j) * cols + col];
    }

    __syncthreads();

    // ---- 写阶段 ----
    // 转置后,output 的子块:
    //   行 [blockIdx.x*TILE, blockIdx.x*TILE + TILE)  ← 原来是 input 的列
    //   列 [blockIdx.y*TILE, blockIdx.y*TILE + TILE)  ← 原来是 input 的行
    const int outCol     = blockIdx.y * TILE + tx;   // 输出列 = 原输入行
    const int outRowBase = blockIdx.x * TILE + ty;   // 输出行起点 = 原输入列

    #pragma unroll
    for (int j = 0; j < TILE; j += BLOCK_ROWS) {
        const int outRow = outRowBase + j;           // 关键:j 加到行上
        if (outCol < rows && outRow < cols)
            output[(size_t)outRow * rows + outCol] = tile[tx][ty + j];
    }
}

extern "C" void solve(const float* input, float* output, int rows, int cols) {
    if (rows <= 0 || cols <= 0) return;

    dim3 threadsPerBlock(TILE, BLOCK_ROWS);
    dim3 blocksPerGrid((cols + TILE - 1) / TILE,
                       (rows + TILE - 1) / TILE);

    matrix_transpose_kernel<<<blocksPerGrid, threadsPerBlock>>>(input, output, rows, cols);
    cudaDeviceSynchronize();
}

关键是

for (int j = 0; j < TILE; j += BLOCK_ROWS) {

const int outRow = outRowBase + j; // 关键:j 加到行上

if (outCol < rows && outRow < cols)

output(size_t)outRow \* rows + outCol = tiletxty + j;

}

如果让block都等于0的话,那么base row和col就是ty,tx,那么最后就是outputtytx=tiletxty]很简单的转置。接下来考虑block x增加,此时base row下移,但他不应该影响与tile的对应关系,因为tile只有一块,所以应该还是和block x等于0时一样,去tile的同样的位置去找。需要注意的是,为什么base row对应的是block x,而不是y,因为这样out才对应input矩阵的block级转置,而thread是对应tile级的转置。

相关推荐
诺鸭船长1 小时前
上帝之手Blender丨从入门到榨干
人工智能
lucas_AI1 小时前
第 9 讲 · 编译期优化:让编译器和反汇编告诉你真相
人工智能
无限压榨切图仔1 小时前
加了“去 AI 味”Skill,水稿还是水:AI 写作流程缺的不是润色
人工智能·程序员
天远数科1 小时前
零信任架构实战:基于天远车型识别精准构建自动化二手车评估网关
人工智能·ai·工具分享
用户1917291270831 小时前
多 Agent 并行不打架:worktree 隔离与反馈回流落地(附脚本)
人工智能
亦暖筑序1 小时前
AgentScope Java 实战:Agent 的状态存在哪、怎么恢复、怎么隔离?
人工智能·后端·agent
jsl_jsl_jsl1 小时前
《Bun 后端怎么变桌面软件:Tauri 2 三进程架构与崩溃自愈》
人工智能
lucas_AI1 小时前
第 10 讲 · PGO 实战:让程序的真实运行数据指导编译
人工智能
lucas_AI1 小时前
第 8 讲 · oeAware 与中断绑核:把手工调优自动化
人工智能