CuPy代码优化:如何加速嵌套for循环
优化方案
核心优化思路
原代码的三层Python循环会带来显著的CPU-GPU调度开销,多次创建中间张量也会浪费内存带宽。我们通过向量化xb维度的计算减少循环层数,同时合并部分einsum步骤降低中间内存占用,所有中间张量规模均不超过dim^4,符合约束要求。
优化后的代码
import numpy as np import cupy as cp from time import perf_counter dim = 60 T_final = cp.random.rand(dim,dim,dim,dim) T_start = cp.random.rand(dim,dim,dim,dim) U = cp.random.rand(dim,dim,dim) # 预先转置T_start,方便批量处理xb维度 T_start_xb_first = T_start.transpose(1, 0, 2, 3) # shape: (xb, xf, k, s) cp.cuda.Stream.null.synchronize() start = perf_counter() for xf in range(dim): for yu in range(dim): # 合并B和C的计算,直接得到所有xb对应的C张量,避免创建中间B C_all = cp.einsum("ij, kim, xkjs->xms", U[:,:,yu], T_start[xf,:,:,:], T_start_xb_first[:, xf, :, :]) # 批量计算并赋值T_final的对应切片 T_final[xf,:,yu,:] = cp.einsum("msc, xms->xc", U, C_all) cp.cuda.Stream.null.synchronize() print(perf_counter()-start)
额外优化建议
- 替换部分einsum为tensordot/matmul:对于简单张量收缩,
cp.tensordot或cp.matmul的底层实现通常比einsum更高效。例如C_all的计算可拆分为两步tensordot:B = cp.tensordot(T_start[xf,:,:,:], U[:,:,yu], axes=1) # 等价于原einsum生成的B C_all = cp.tensordot(B, T_start_xb_first[:, xf, :, :], axes=([0,2], [1,2])) - 启用自动混合精度:若计算精度允许,使用
cp.amp.autocast()上下文管理器,可进一步提升GPU计算效率。 - 自定义CUDA核函数:若性能仍未达标,可使用
cp.jit.rawkernel编写自定义CUDA核,完全控制内存访问模式与计算流程,最大化GPU利用率。
内容的提问来源于stack exchange,提问作者Indiano
相关产品推荐
相关产品推荐

