在现代多核处理器中,我们通常有一个本地 L1 缓存,但有一个共享的 L2 缓存。是否可以绕过内存的某些部分的 L1 缓存,同时仍然使用 L2 缓存?我想这样做是为了提高时序可预测性,但可能会以性能为代价。
2 回答
缓存
我强烈怀疑您误解了缓存的作用和用途。
从内存内容的角度来看,缓存是透明的。如果一个核心写入一个内存位置,那么其他所有缓存(L1、L2、L3 等)的核心,无论是否共享,碰巧正在缓存该位置也将得到更新。
请注意,这并不意味着核心无法争夺价值。您仍然可以有一个竞争条件,即一个核心在另一个写入它之前读取一个位置的分数“得到错误的值”。此外,无论您的 CPU 是否具有任何类型的缓存,都会发生这种情况。要解决“排序”问题,您必须在源代码中使用信号量或其他 IPC 原语。
一些缓存系统确实允许您向它们“放置提示”。Matthieu Rouget 用 __builtin_prefetch 举了一个例子。这类事情允许程序员告诉缓存系统它可能值得提前获取一些数据。一些系统(例如PowerPC 7450)允许程序员使用部分缓存作为内存而不是缓存,这是程序员缓存控制的终极选择。
但是,这些都不会对所有缓存所具有的内存视图产生任何影响。如果一个缓存的内容得到更新,其余的也会更新。
缓存和性能编程
最优秀的程序员能够通过围绕缓存行为进行编码来从 CPU 中提取峰值性能。在那个领域,人们通常会发现自己希望缓存根本不存在。这方面的终极体现是 PS3 中的 Cell 处理器。其上的数学核心根本没有缓存。相反,您实际上必须自己进行所有数据获取并在源代码中自己写回,而不是将其留给某个缓存来再次猜测您的程序将要求什么数据。做对了,性能仍然非常好。
总线监听
一些 CPU 没有缓存总线侦听功能,这在编写设备驱动程序时可能是一个特殊问题。总线侦听是一种机制,CPU 高速缓存借此发现内存内容被 CPU 内核以外的东西更新(例如,通过 DMA 控制器从设备读取数据)。反过来也是一样 - 来自内存的 DMA 获取当前卡在缓存中的值。如今,AFAIK 几乎所有的 CPU 都进行总线侦听,因此这不太可能成为问题。
在具有 IO 和内存地址空间的系统(例如 Intel)上,我认为 I/O 地址空间无论如何都不会被缓存。对于具有内存映射设备的系统,它们的内存通常也不缓存,并且操作系统以这种方式设置 CPU(请参阅this)。
时序可预测性
回到您提出问题的原因 - 时间可预测性。您可能使用了错误的技术。如果您的系统有时间限制,问题是主内存写入时间的变化,那么坦率地说,首先使用多核 CPU 听起来像是错误的事情。@Griwes在这一点上是完全正确的(实际上是整个评论)。您更可能需要求助于纯硬件设计,类似于 FPGA 的东西(请不要评论固件是否真的是软件!)。
如果,正如我所怀疑的那样,您实际上是在尝试避免使用信号量和其他 IPC 原语来同步系统中的两个线程,那么无论是否共享缓存,您都不会成功。您需要使用信号量等来使您的代码正常工作。
据我所知,主流 CPU 上的 L1 缓存是无法绕过的。
但是,为了实现您的目标(即避免可能导致时序测量变化的缓存未命中),您可以尝试让编译器将数据预取到缓存中。
如果您使用 GCC 或 LLVM,请参阅__builtin_prefetch。
但是,您的问题很模糊,我不确定您的建议是否适合您的需求。