写入内存时缓存的作用是什么?
What is the cache's role when writing to memory?
我有一个函数,它只进行很少的读取,但对 RAM 进行大量写入。当我 运行 它在同一个核心(主线程)上多次时,它 运行 比我每 运行 在一个新线程上启动该函数快大约 5 倍(这不'保证在 运行s 之间使用相同的内核,因为我在 运行s 之间启动和加入。
这表明缓存正被大量用于写入过程,但我不明白是如何发生的。我以为缓存只对读取有用。
现代处理器通常有写缓冲区。原因是写入在第一近似值中是纯粹的汇。处理器在执行下一条指令之前通常不必等待存储到达一致的内存层次结构。
(旁白:显然存储 不是 纯汇。稍后从写入的内存位置读取应该 return 写入值,因此处理器必须窥探写缓冲区,并停止读取或将写入的值转发给它)
显然,此类缓冲区的大小有限,因此当缓冲区已满时,程序中的下一个存储将无法执行并暂停,直到缓冲区中的一个槽被一个较旧的存储在架构上变得可用可见。
通常,写入离开缓冲区的方式是在将值写入缓存时(因为很多写入 是 实际上会很快再次读回,想想程序堆栈举个例子)。如果写入只设置了缓存行的一部分,则缓存行的其余部分必须保持不变,因此必须从内存层次结构中加载它。
有一些方法可以避免加载旧的缓存行,例如非临时存储、写入组合内存或缓存行清零指令。
非临时存储和写入合并内存合并相邻的写入以填充整个缓存行,将新的缓存行发送到内存层次结构以替换旧的。
POWER 有一条指令将完整的缓存行清零 (dcbz
),这也消除了从内存中加载旧值的需要。
x86 和 AVX512 有缓存行大小的寄存器,这表明对齐的 zmm
-寄存器存储 可以 避免加载旧的缓存行(虽然我不知道是否确实如此)。
请注意,其中许多技术与相应处理器架构的通常内存排序不一致。使用它们可能需要在多线程操作中额外 fences/barriers。
我有一个函数,它只进行很少的读取,但对 RAM 进行大量写入。当我 运行 它在同一个核心(主线程)上多次时,它 运行 比我每 运行 在一个新线程上启动该函数快大约 5 倍(这不'保证在 运行s 之间使用相同的内核,因为我在 运行s 之间启动和加入。
这表明缓存正被大量用于写入过程,但我不明白是如何发生的。我以为缓存只对读取有用。
现代处理器通常有写缓冲区。原因是写入在第一近似值中是纯粹的汇。处理器在执行下一条指令之前通常不必等待存储到达一致的内存层次结构。
(旁白:显然存储 不是 纯汇。稍后从写入的内存位置读取应该 return 写入值,因此处理器必须窥探写缓冲区,并停止读取或将写入的值转发给它)
显然,此类缓冲区的大小有限,因此当缓冲区已满时,程序中的下一个存储将无法执行并暂停,直到缓冲区中的一个槽被一个较旧的存储在架构上变得可用可见。
通常,写入离开缓冲区的方式是在将值写入缓存时(因为很多写入 是 实际上会很快再次读回,想想程序堆栈举个例子)。如果写入只设置了缓存行的一部分,则缓存行的其余部分必须保持不变,因此必须从内存层次结构中加载它。
有一些方法可以避免加载旧的缓存行,例如非临时存储、写入组合内存或缓存行清零指令。
非临时存储和写入合并内存合并相邻的写入以填充整个缓存行,将新的缓存行发送到内存层次结构以替换旧的。
POWER 有一条指令将完整的缓存行清零 (dcbz
),这也消除了从内存中加载旧值的需要。
x86 和 AVX512 有缓存行大小的寄存器,这表明对齐的 zmm
-寄存器存储 可以 避免加载旧的缓存行(虽然我不知道是否确实如此)。
请注意,其中许多技术与相应处理器架构的通常内存排序不一致。使用它们可能需要在多线程操作中额外 fences/barriers。