__builtin_prefetch,它读取了多少数据?

23

我正在尝试通过使用RK4优化一些C++代码

__builtin_prefetch

我无法弄清如何预取整个结构。
我不明白有多少const void *addr被读取。我希望下一个fromto的值被加载。
for (int i = from; i < to; i++)
{
    double kv = myLinks[i].kv;
    particle* from = con[i].Pfrom;
    particle* to = con[i].Pto;
    //Prefetch values at con[i++].Pfrom & con[i].Pto;
    double pos = to->px- from->px;
    double delta = from->r + to->r - pos;
    double k1 = axcel(kv, delta, from->mass) * dt; //axcel is an inlined function
    double k2 = axcel(kv, delta + 0.5 * k1, from->mass) * dt;
    double k3 = axcel(kv, delta + 0.5 * k2, from->mass) * dt;
    double k4 = axcel(kv, delta + k3, from->mass) * dt;
    #define likely(x)       __builtin_expect((x),1)
    if (likely(!from->bc))
    {
            from->x += (( k1 + 2 * k2 + 2 * k3 + k4) / 6);
    }
}

链接: http://www.ibm.com/developerworks/linux/library/l-gcc-hacks/


我认为这种微观优化除了学习目的外没有太大意义。现代CPU自己非常擅长预取操作。 - ronag
1
可能是这样,但我有一个函数被调用了将近10亿次。 - Mikhail
什么是“RK4”? - Peter Mortensen
2个回答

31
我认为它只会发出一个FETCH机器指令,该指令基本上会获取一个缓存行,其大小取决于处理器。
您可以使用例如__builtin_prefetch (con[i+3].Pfrom)。根据我的(小型)经验,在这样的循环中,最好提前预取多个元素。
不要过于频繁地使用__builtin_prefetch(即不要在循环内放置很多此类语句)。如果需要它们,请测量性能提升,并使用GCC优化(至少-O2)。如果你非常幸运,手动使用__builtin_prefetch可以将您的循环性能提高10或20%(但也可能会影响它)。
如果这样的循环对您非常重要,则可以考虑在OpenCL或CUDA的GPU上运行它(但这需要用OpenCL或CUDA语言重新编码一些例程,并对它们进行调整以适应您特定的硬件)。
还要使用较新的GCC编译器(最新版本为4.6.2),因为它在这些领域取得了很多进展。

(添加于2018年1月:)

处理器和编译器在缓存方面都取得了很多进展,因此在今天(2018年)使用__builtin_prefetch似乎不那么有用了。请务必进行基准测试。


7
如果你要这样做,请确保在之前和之后对你的循环进行基准测试。有可能会让性能变得更差或者没有任何改善。 - 111111
6
感谢您的帖子。我进行了3个基准测试:无优化= 100%,预读[i + 3] = 100%,以及使用[i + 10] = 200% +。所有测试都是在-03和快速数学下完成的。 - Mikhail

18

它读取缓存行。缓存行大小可能会有所变化,但现代 CPU 上最常见的大小为 64 字节。如果您需要读取多个缓存行,请查看 prefetch_range


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接