You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetson Nano(Maxwell架构)启用L1/Texture缓存对NVCC(CUDA10.2)的性能影响

CUDA全局内存与纹理内存双线性插值的性能疑问解答

实验背景

为对比纹理内存与全局内存在双线性插值中的表现,实现了两个CUDA内核:

全局内存双线性插值核

__global__ void GlobalBilinear(typeImg * inPtr, typeOutImg* outPtr, int width, int height)
{
    int ix = blockIdx.x * blockDim.x + threadIdx.x;
    int iy = blockIdx.y * blockDim.y + threadIdx.y;

    __shared__ float val[1024];

    if(ix < width && iy < height)
    {
        val[threadIdx.x + blockDim.x*threadIdx.y] 
                =   (1.0f - alpha) * (1.0f - beta) * uint2float(inPtr[ix + width * iy]) + 
                    alpha * (1.0f - beta) * uint2float(inPtr[ix + 1 + width * iy])      +
                    (1.0f - alpha) * (beta)*uint2float(inPtr[ix + width * (iy + 1)])     +
                    alpha * (beta)*uint2float(inPtr[ix + 1 + width * (iy + 1)]);
    }
}

纹理内存双线性插值核

__global__ void MemoryBilinear2DTexture(cudaTextureObject_t texObj, typeOutImg* outPtr, int width, int height)
{
    int ix = blockIdx.x * blockDim.x + threadIdx.x;
    int iy = blockIdx.y * blockDim.y + threadIdx.y;

    __shared__ float val[1024];
    if(ix < width && iy < height)
    {
        val[threadIdx.x + blockDim.x*threadIdx.y] = (tex2D<typeOutImg>(texObj, ix + 1.0f, iy + 1.0f));
    }
}

测试结果

对1000×1000的8位图像进行50次运行计时:

  • 默认编译(L1缓存禁用,-Xptxas -dlcm=cg):
    • 全局内存核耗时:37.87073 ms
    • 纹理内存核耗时:25.75578 ms
  • 手动启用L1缓存(-Xptxas -dlcm=ca):
    • 全局内存核耗时:48.90469 ms
    • 纹理内存核耗时:33.65562 ms

L1启用时的nvprof分析结果

**Kernel: GlobalBilinear(void*, void*, int, long)**
global_hit_rate         Global Hit Rate in unified l1/tex      72.48%      72.48%      72.48%
tex_cache_transactions  Unified Cache Transactions      504000      504000      504000
**Kernel: MemoryBilinear2DTexture(__int64, void*, int, long)**
global_hit_rate         Global Hit Rate in unified l1/tex       0.00%       0.00%       0.00%
tex_cache_transactions  Unified Cache Transactions      250000      250000      250000

问题解答

1. 为何启用L1缓存会带来性能下降?

从nvprof数据可以拆解出核心原因:

  • 全局内存核的双线性实现中,每个线程要读取4个相邻全局内存地址。启用L1后,这些访问会占用L1缓存空间,相邻线程的缓存行容易出现覆盖、冲突,导致额外的缓存读写开销;同时L1与纹理缓存共享硬件资源,启用L1会挤占纹理缓存的可用空间,直接降低纹理核的访问效率。
  • 默认禁用L1时,全局内存访问直接走L2缓存。对于这种规则的连续+相邻访问模式,L2的预取机制和带宽表现更优——L1容量小,容易触发缓存失效,反而增加了往返L2的次数,整体延迟上升。

2. 为何NVCC默认禁用全局内存访问的L1缓存?

NVCC的默认设置是基于通用场景的最优权衡:

  • 多数通用CUDA内核的全局内存访问要么是规则连续访问(此时L2预取机制已能高效工作,L1增益有限),要么是随机访问(L1容量小,命中率低,反而增加缓存开销)。
  • 在统一缓存架构中,L1与纹理缓存共享资源。禁用L1可让更多资源留给纹理缓存,这对图形、图像处理这类CUDA常见应用场景更友好。
  • 启用L1可能引发缓存冲突、额外延迟等“意外”性能损耗,默认禁用能让多数通用内核的表现更稳定。

内容的提问来源于stack exchange,提问作者rooody

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 16:33:25