【问题标题】:gcc, what is the purpose of asm volatile ("" : : "r" (x))gcc,asm volatile ("" : : "r" (x)) 的目的是什么
【发布时间】:2014-07-09 04:37:34
【问题描述】:

我在 C 源代码中看到了以下这样的代码,由 gcc 在 Linux 上编译(用于计算机):

extern double prices[4000];

void somefunction()
{
  //this function is called again after each 5 seconds interval

  //some long codes that use prices[]
  // ...

  int i;
  for (i=0; i<4000; i++)
  {
      asm volatile ("" : : "r" (prices[i]));
  }
}

所以我有一些问题:

  1. 这里的内联汇编的目的是什么?
  2. 看起来价格[i]是值,应该是指针吗?
  3. 在我看来,asm代码只是将prices[i]放入寄存器供以后参考,但是循环数是4000,这没有意义(计算机没有这么多寄存器)

【问题讨论】:

  • volatile 表示外部影响可能会改变数据:不要指望每次需要访问时都通过重新加载数据来保持稳定。

标签: c gcc assembly inline-assembly volatile


【解决方案1】:

volatile 关键字告诉编译器不允许移动这个汇编块。

asm ("" ::: "memory") 是一个简单的编译器栅栏。

来自here

您可以通过编写 asm 之后的关键字 volatile。 [...] volatile 关键字表示 该指令具有重要的副作用。 GCC 不会删除 volatile asm(如果可访问)。

【讨论】:

    【解决方案2】:

    asm volatile 强制编译将 prices[i] 加载到某个寄存器中(对于每个循环执行来说,这将是同一个寄存器,您仍然会使用一个寄存器来执行 4000 次循环)。

    如果您只是在没有volatile 的情况下编写了asm,编译器可以通过删除(或移动)整个语句进行优化,然后删除整个循环,因为它什么都不做。

    尝试用

    编译你的foo.c代码
     gcc -O0 -fverbose-asm -S foo.c -o foo-O0.s
     gcc -O1 -fverbose-asm -S foo.c -o foo-O1.s
     gcc -O2 -fverbose-asm -S foo.c -o foo-O2.s
     gcc -O3 -fverbose-asm -S foo.c -o foo-O3.s
    

    并查看生成的 foo-O*.s 文件(例如,使用编辑器或像 less 这样的寻呼机)使用和不使用 volatile 关键字

    【讨论】:

    • 其实因为没有输出参数,所以volatile是隐含的。
    • 大卫沃尔弗德是正确的。实际上 volatile 关键字不在问题中。我只想知道代码的作用:asm volatile ("" : : "r" (prices[i]));
    • Basile Starynkevitch 似乎回答了我的一个问题,但是,正如我所说,CPU 中的寄存器数量是有限的,因此由于 4000 个循环,代码看起来毫无用处,对吗?还是有其他用途?
    • 除此之外,@basile 所说的是正确的。除非这段代码有更多内容(引号内的东西?),否则这是一个无用的浪费时间的循环。
    • 如果这是一个求职面试问题,我可能会外交地推测它试图加热缓存。那么我会说这是一个无用的浪费时间的循环。
    【解决方案3】:

    在与编写代码的人讨论后,他说他正在尝试将变量提取到 CPU 缓存中(L1/L2/L3)

    【讨论】:

    • 我相信这是我之前推测的。是的,这会将内容读入缓存。这是否比让 cpu 自己管理它提供任何实际好处是值得商榷的。它更有可能做它所做的事情:给以后处理代码的人带来维护问题,以及可移植性问题。
    • @DavidWohlferd 如何使用 gcc prefetch builtin 而不是这个方法?你指的是哪一个?
    • 操作系统会在你每次访问时自动将内存加载到cpu的缓存中(例如当你将值加载到价格数组中时)。它还会在选择时自动将东西扔出缓存。没有办法将东西“保留”在那里。还要记住,cpu 的缓存在所有正在运行的进程之间共享。因此,尽管您可能认为将这些价格移动到缓存中是一个绝妙的主意,但操作系统可以决定某些设备驱动程序信息更有用,并将您所有的东西都扔掉。所以我的偏好是(几乎总是)让 cpu/OS 处理这个。
    • 最后一个想法:在某些性能非常密集的例程中进行这种类型的优化是有意义的。如果您想了解这是否真的在这种情况下有所作为,请使用分析器并对其计时。您甚至可以将其与使用预取进行比较。得知这里节省了任何人类可感知的时间,我会感到非常惊讶。发现它让事情变慢一点也不奇怪。
    猜你喜欢
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-05
    • 1970-01-01
    • 2015-07-05
    相关资源
    最近更新 更多