为什么在二维卷积操作中,将宽度(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) 的内存布局。

相关推荐
千宇宙航2 小时前
闲庭信步使用图像验证平台加速FPGA的开发:第九课——图像插值的FPGA实现
图像处理·计算机视觉·缓存·fpga开发
全栈凯哥3 小时前
20.缓存问题与解决方案详解教程
java·spring boot·redis·后端·缓存
Hellyc10 小时前
用户查询优惠券之缓存击穿
java·redis·缓存
鼠鼠我捏,要死了捏12 小时前
缓存穿透与击穿多方案对比与实践指南
redis·缓存·实践指南
汤姆大聪明19 小时前
Redis 持久化机制
数据库·redis·缓存
kk在加油21 小时前
Redis数据安全性分析
数据库·redis·缓存
hcvinh2 天前
CANDENCE 17.4 进行元器件缓存更新
学习·缓存
墨着染霜华2 天前
Caffeine的tokenCache与Spring的CaffeineCacheManager缓存区别
java·spring·缓存
weixin_438335402 天前
Redis:分组与设备在 Redis 中缓存存储设计
redis·缓存·bootstrap
秋也凉2 天前
redis的命令集合
数据库·redis·缓存