【问题标题】:How do declare a memory range as uncacheable using gcc on x86 platform?如何在 x86 平台上使用 gcc 将内存范围声明为不可缓存?
【发布时间】:2011-09-14 06:32:41
【问题描述】:

虽然我已经阅读了有关此的 movntdqa 指令,但已经找到了一种干净的方法来表达不可缓存的内存范围或读取数据,以免污染缓存。 我想从 gcc 做到这一点。我的主要目标是交换到大数组中的随机位置。由于数据很少,因此希望通过避免缓存来加速此操作。

【问题讨论】:

  • 在 Windows 上肯定有办法做到这一点。不过,我不确定 Linux 上的 GCC。但是,我不确定您是否要将读取内存声明为不可缓存。尽管您不会污染缓存,但您(可能)会为每次访问支付全部内存延迟。
  • 我同意它可能不会提高性能。但我很高兴知道如何使用此功能。
  • 没有办法禁用cpu缓存。你也不会想要,它会让它变得非常缓慢。未缓存的内存读取很容易花费一百多个周期。
  • @Hans Passant:你的第一句话是错误的——例如在 x86 架构上,您可以通过在 CR3 寄存器中设置 PCD 位来完全禁用缓存,或者通过为特定页面设置 PCD 位来仅针对某些页面禁用缓存。至于第二个说法,Sandeep 描述了一种缓存可能真的没用的情况——虽然它可能不会加快主应用程序的速度,但它可以为其他线程节省宝贵的缓存。
  • @HansPassant 当然可以禁用缓存。您可以为此使用 MTRR,或为此使用页面属性表。

标签: gcc assembly x86 sse


【解决方案1】:

我认为您所描述的是Memory Type Range Registers。您可以在 Linux 下使用 /proc/mttr / ioctl(2) 控制这些(如果可用并且您是用户 0),请参阅 here 示例。由于它适用于 物理 地址范围,我认为您将很难以合理的方式使用它。

更好的方法是查看编译器内在函数 GCC provides 并找到一个或多个表达您的意图的。看看 Ulrich Drepper 关于“每个程序员都应该了解的内存”系列,特别是处理绕过缓存的 part 5。看起来_mm_prefetch(ptr, _MM_HINT_NTA) 可能适合您的需求。

与以往一样,在性能方面 - 衡量、衡量、衡量。 Drepper 的系列中有优秀的部分详细介绍了如何做到这一点 (part 7) 以及代码示例和其他在加快代码的内存性能时可以尝试的策略。

【讨论】:

    【解决方案2】:

    来自 user786653 的所有好建议;特别是 Ulrich Drepper 的文章。我会补充:

    • 无论是否未缓存,VM 硬件都必须在容量有限的 TLB 中查找页面信息。不要低估 TLB 抖动对随机访问性能的影响。如果您还没有,请参阅the results here 了解为什么您真的希望将 huge pages 用于您的数组数据而不是很小的 4K 默认值(这可以追溯到“640K 应该对任何人来说都足够了”)。当然,如果你说的是非常大的数组,甚至比一个装满 2MB 页面的 TLB 还大,即使这样也无济于事。

    • 你有什么反对'nt'指令(例如_mm_stream_ps内在)?我不相信声明页面未缓存会比适当使用这些页面获得更好的性能,而且它们比替代品更容易使用。不过,我很想看到相反的证据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-04
      • 1970-01-01
      • 2012-04-11
      • 1970-01-01
      • 2020-05-07
      • 2015-10-02
      相关资源
      最近更新 更多