为什么在二维卷积操作中,将宽度(W)维度放在高度(H)之前会破坏空间局部性原则,并影响缓存性能

空间局部性原则

空间局部性指的是程序倾向于访问与最近访问过的内存位置接近的内存位置。对于深度学习模型中的张量数据,这意味着当处理图像或特征图时,如果能够连续地访问相邻像素的数据,那么可以最大化利用CPU/GPU缓存,因为缓存通常加载的是连续的一块内存。

二维卷积操作

在二维卷积中,过滤器(kernel)会在输入特征图上滑动,依次计算每个输出像素值。这个过程涉及到沿着高度(H)和宽度(W)两个方向移动过滤器。具体来说:

  • 遍历顺序:通常情况下,遍历是从左到右(W方向),从上到下(H方向)。也就是说,先完成一行内所有元素的计算,然后移动到下一行。

  • 内存布局影响:如果我们使用 (N, H, W, C) 的格式,那么在遍历同一行中的相邻元素时,内存地址是连续的。例如,在读取一个3x3过滤器窗口内的数据时,假设我们正在处理第一行的前三个元素 0,0, 0,1, 0,2,这些元素在内存中是连续存储的,这使得缓存能够高效地预取和加载这些数据,提高访问速度。

  • 如果选择 (N, W, H, C)

  • 破坏空间局部性:但是,如果我们将张量维度调整为 (N, W, H, C),即宽度(W)维度排在高度(H)之前,那么在遍历同一行中的相邻元素时,内存地址不再是连续的。比如,当我们尝试按照常规的从左到右、从上到下的顺序遍历时,实际上是在跳跃式地访问不同行的数据,而不是连续访问同一行的数据。这会导致每次访问新元素时都需要从主内存重新加载数据,无法有效利用缓存,从而降低了缓存命中率和整体性能。

示例

假设有一个简单的4x4特征图(忽略批次N和通道C),按 (N, H, W, C) 布局,它在内存中可能是这样的(简化表示):

复制代码
[H=0, W=0], [H=0, W=1], [H=0, W=2], [H=0, W=3],
[H=1, W=0], [H=1, W=1], [H=1, W=2], [H=1, W=3],
[H=2, W=0], [H=2, W=1], [H=2, W=2], [H=2, W=3],
[H=3, W=0], [H=3, W=1], [H=3, W=2], [H=3, W=3]

而按 (N, W, H, C) 布局,则变成:

复制代码
[W=0, H=0], [W=1, H=0], [W=2, H=0], [W=3, H=0],
[W=0, H=1], [W=1, H=1], [W=2, H=1], [W=3, H=1],
[W=0, H=2], [W=1, H=2], [W=2, H=2], [W=3, H=2],
[W=0, H=3], [W=1, H=3], [W=2, H=3], [W=3, H=3]

在这个新的布局中,当你想要按行遍历时,你实际上是跨着不同的行来访问数据,这导致了较差的空间局部性和缓存性能。

因此,为了保持良好的空间局部性和高效的缓存利用,在进行二维卷积操作时,通常推荐使用 (N, H, W, C) 的内存布局。

相关推荐
仍然.7 小时前
Redis---缓存
数据库·redis·缓存
骇客野人8 小时前
微服务多级缓存架构设计
缓存·微服务·架构
禾小西14 小时前
05丨Redis 内存快照:宕机后,如何实现快速恢复?
数据库·redis·缓存
李纲明16 小时前
WordPress 站点变慢:按 TTFB → 缓存 → 查询 → 前端 分层排查(含配置注意)
前端·缓存·性能优化·wordpress·后端开发
我不会插花弄玉16 小时前
4.string类型【由浅入深-redis】
数据库·redis·缓存
Riwuarua17 小时前
从近似0基础开始FPGA开发——Part.23:AXI/AXIS 数据搬运、DMA 与 DDR 缓存架构设计
缓存·fpga开发
姜鱼问生1 天前
Nginx 缓存命中率监控:从 X-Cache-Status 到实时统计
运维·nginx·缓存
weixin199701080162 天前
《1688图片空间API踩坑:img.upload 与 album.* 的防盗链与CDN缓存问题》(附Python源码)
开发语言·python·缓存
hweiyu002 天前
Redis命令:BLPOP
redis·缓存