如何在ARM中使用pld指令

时间:2013-04-16 08:28:52

标签: c gcc arm

我这样使用它。

__pld(pin[0], pin[1], pin[2], pin[3], pin[4]);

但是我收到了这个错误。

undefined reference to `__pld'

我错过了什么?我是否需要包含头文件或其他内容?我正在使用ARM Cortex A8,它是否支持 pld 指令?

4 个答案:

答案 0 :(得分:6)

this answer所示,您可以按照Clark使用内联汇编程序。 __builtin_prefetch也是一个很好的建议。需要知道的一个重要事实是pld指令如何作用于ARM;对于某些处理器,它什么都不做对于其他人,它将数据带入缓存。这仅对读取操作(或读取/修改/写入)有效。另一件需要注意的是,如果它在您的处理器上运行,它会获取整个缓存行。因此,获取pin数组的示例不需要指定所有成员。

通过确保pld数据与缓存对齐,您将获得更高的性能。另一个问题是,通过查看前面的代码,您只能获得读取变量的性能。在某些情况下,您只是到引脚阵列。 预取这些项目没有任何价值。 ARM有一个写缓冲区,因此写入被批处理并自动突发到SDRAM芯片。

将所有读取数据分组到缓存行中将显示最大的性能提升;可以使用单个pld预先修整整行。此外,当您取消滚动循环时,编译器将能够看到这些读取,并且如果可能的话将更早地安排它们,以便它们被填充到缓存中;至少对于一些ARM cpu来说。

另外,您可以考虑,

 __attribute__((optimize("prefetch-loop-arrays")))

本着另一个问题的公认答案的精神;可能编译器已经在-O3启用了它,如果它对你指定的CPU有效。

可以使用--param NAME=VALUE指定各种编译器选项,以允许您在内存子系统上为编译器提供提示。如果你得到正确的参数,这可能是一个非常有效的组合。

  • prefetch-latency
  • simultaneous-prefetches
  • l1-cache-line-size
  • l1-cache-size
  • l2-cache-size
  • min-insn-to-prefetch-ratio
  • prefetch-min-insn-to-mem-ratio

确保为支持-mcpu的编译器指定pld。如果一切正常,编译器应该自动为您执行此操作。但是,有时你可能需要手动完成。

供参考,这里是gcc-4.7.3的 ARM prefetch loop arrays代码激活。

  /* Enable sw prefetching at -O3 for CPUS that have prefetch, and we have deemed
     it beneficial (signified by setting num_prefetch_slots to 1 or more.)  */
  if (flag_prefetch_loop_arrays < 0
      && HAVE_prefetch
      && optimize >= 3
      && current_tune->num_prefetch_slots > 0)
    flag_prefetch_loop_arrays = 1;

答案 1 :(得分:3)

尝试http://www.ethernut.de/en/documents/arm-inline-asm.html

在GCC中,它可能如下所示:

示例来自:http://communities.mentor.com/community/cs/archives/arm-gnu/msg01553.html  以及pld:

的用法
   __asm__ __volatile__(
    "pld\t[%0]"
    :
    : "r" (first) );

答案 2 :(得分:2)

你可能想看看gcc的__builtin_prefetch。为了您的方便,我在这里复制了它:

  

此函数用于通过在访问数据之前将数据移入缓存来最小化缓存未命中延迟。您可以将对__builtin_prefetch的调用插入到您知道可能很快访问的内存中数据地址的代码中。如果目标支持它们,将生成数据预取指令。如果在访问之前足够早地完成预取,那么在访问数据时数据将在缓存中。

     

addr的值是要预取的内存的地址。有两个可选参数,rw和locality。 rw的值是编译时常量1或0;一个意味着预取正在准备写入内存地址和零,默认值意味着预取正在准备读取。值locality必须是0到3之间的编译时常量整数。值为零意味着数据没有时间局部性,因此在访问后不需要将其留在缓存中。值为3意味着数据具有高度的时间局部性,并且应该保留在所有级别的高速缓存中。值1和2分别表示低或中等程度的时间局部性。默认值为三。

     for (i = 0; i < n; i++)
       {
         a[i] = a[i] + b[i];
         __builtin_prefetch (&a[i+j], 1, 1);
         __builtin_prefetch (&b[i+j], 0, 1);
         /* ... */
       }
     

如果addr无效,则数据预取不会生成错误,但地址表达式本身必须有效。例如,如果p-&gt; next不是有效地址,则p-> next的预取将不会出错,但如果p不是有效地址,则评估将失败。

     

如果目标不支持数据预取,则会评估地址表达式是否包含副作用,但不会生成其他代码,并且GCC不会发出警告。

答案 3 :(得分:0)

undefined reference to `__pld'

要回答有关未定义引用的问题,__pld是ARM编译器内在函数。请参阅ARM手册中的__pld intrinsic

也许GCC不承认ARM的内在性。