我像这样使用它。
__pld(pin[0], pin[1], pin[2], pin[3], pin[4]);
但我得到这个错误。
undefined reference to `__pld'
我错过了什么?我需要包含头文件或其他东西吗?我使用的是 ARM Cortex A8,它甚至支持pld指令吗?
如this answer所示,您可以按照Clark使用内联汇编程序。 __builtin_prefetch
也是一个很好的建议。要知道的一个重要事实是pld
指令如何作用于 ARM;对于某些处理器,它什么也不做。对于其他人,它将数据带入缓存。这仅对读取操作(或读取/修改/写入)有效。要注意的另一件事是,如果它确实在您的处理器上工作,它会获取整个缓存行。所以获取pin
数组的例子,不需要指定所有成员。
通过确保pld
数据与缓存对齐,您将获得更高的性能。另一个问题是,通过查看前面的代码,您只能通过读取的变量获得性能。在某些情况下,您只是在写入pin 数组。预取这些项目没有任何价值。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;
试试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) );
你可能想看看 gcc 的__builtin_prefetch
. 为了您的方便,我在这里复制了它:
此功能用于通过在访问数据之前将数据移动到缓存中来最小化缓存未命中延迟。您可以将对 __builtin_prefetch 的调用插入到您知道内存中可能很快会被访问的数据地址的代码中。如果目标支持它们,将生成数据预取指令。如果预取在访问之前足够早地完成,那么数据将在访问时位于缓存中。
addr 的值是要预取的内存地址。有两个可选参数,rw 和 locality。rw 的值是编译时常数 1 或 0;1 表示预取正在准备写入内存地址,默认值为零表示预取正在准备读取。值局部性必须是介于 0 和 3 之间的编译时常量整数。值为零表示数据没有时间局部性,因此在访问后无需将其留在缓存中。值为 3 表示数据具有高度的时间局部性,应尽可能保留在所有级别的缓存中。一和二的值分别表示低或中等程度的时间局部性。默认值为三个。
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->next 不是有效地址,则 p->next 的预取不会出错,但如果 p 不是有效地址,则评估会出错。
如果目标不支持数据预取,如果地址表达式包含副作用但不生成其他代码并且 GCC 不发出警告,则计算地址表达式。
undefined reference to `__pld'
要回答有关未定义引用的问题,__pld
是 ARM 编译器内在的。请参阅ARM 手册中的__pld 内在函数。
也许 GCC 不承认 ARM 固有的。