为什么__builtin_prefetch在这里没有任何影响?

时间:2012-09-19 04:32:28

标签: c++ performance optimization gcc

我正在编写一个解析文件的程序。它由一个主循环组成,逐个字符地解析并处理它们。这是主循环:

char c;
char * ptr;

for( size_t i = 0; i < size ; ++i )
{
    ptr = ( static_cast<char*>(sentenceMap) + i );
    c = *ptr;

    __builtin_prefetch( ptr + i + 1 );

   // some treatment on ptr and c   
}

正如您所看到的,我添加了一条builtin_prefetch指令,希望在我的循环的下一次迭代中放入缓存。我尝试了不同的值:ptr+i+1ptr+i+2ptr+i+10但似乎没有任何改变。

为了测量性能,我使用valgrind的工具cachegrind,它给出了缓存未命中数的指示。在行c = *ptr上,当未设置__builtin_prefetch时,cachegrind记录632,378 DLmr(L3缓存未命中)。但奇怪的是,无论我设置为__builtin_prefetch的参数如何,此值都不会改变。

对此有何解释?

3 个答案:

答案 0 :(得分:11)

那是因为硬件比您早多年。 :)

有一些硬件预取程序可以识别简单的模式并为您进行预取。在这种情况下,您有一个简单的顺序访问模式,这对于硬件预取器来说是微不足道的。

当您拥有硬件无法预测的访问模式时,手动预取非常方便。

以下是一个这样的例子:Prefetching Examples?

答案 1 :(得分:3)

首先,缓存交易的最小单位称为cache line,缓存行可以是例如64字节长,但绝不能小到1字节。因此,当您要求预取时,您需要提前询问当前的兴趣位置。您需要知道缓存行大小,因此不应要求位于同一缓存行中的地址。您还需要不要多次调用预取,因为很快就可能会使用高速缓存行,并在执行指令时创建性能命中。

现代架构还有硬件预取程序的概念,根据您的访问模式可以提前为您预取数据。这应该是大多数时候创建数据访问时间和简单预取一样好。现在,SW预取只能帮助你,如果你能找到一个非常明显的预取数据的地方 - 而不是随机扩散到代码中。例如,在开始处理一段数据之前,如果您只是立即调用prefetch并访问数据,这对您无济于事。您需要尽早完成此操作并在访问数据之前进行其他设置工作。

我建议任何对此类主题感兴趣的人阅读The Software Optimization Cookbook。我一般都处理ARM架构,但我发现这本书非常宝贵。网上还有一些与此问题相关的摘录;请参阅#1#2

答案 2 :(得分:0)

正确的答案是:预取不能改变缓存未命中数,它只是强制它们更早发生:)