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

相关推荐
what丶k1 小时前
深入解析Redis数据持久化:RBD机制原理、实操与生产最佳实践
数据库·redis·缓存
Dreamboat-L4 小时前
Redis及其两种持久化技术详解
数据库·redis·缓存
lead520lyq5 小时前
Golang本地内存缓存
开发语言·缓存·golang
三水不滴5 小时前
Redis缓存更新策略
数据库·经验分享·redis·笔记·后端·缓存
优雅的潮叭7 小时前
cud编程之 reduce
android·redis·缓存
打工的小王7 小时前
redis(三)redis持久化和集群(redis版本:5.0.4)
数据库·redis·缓存
曹天骄10 小时前
基于 Cloudflare Worker 构建分布式测速调度系统:KV 与 D1 数据层设计实战教程
分布式·缓存
三水不滴10 小时前
Redis 持久化机制
数据库·经验分享·redis·笔记·缓存·性能优化
heartbeat..12 小时前
Redis 中的锁:核心实现、类型与最佳实践
java·数据库·redis·缓存·并发
Prince-Peng12 小时前
技术架构系列 - 详解Redis
数据结构·数据库·redis·分布式·缓存·中间件·架构