我正在尝试使用
优化某些C ++(RK4)__builtin_prefetch
我无法弄清楚如何预取整个结构。
我不明白有多少const void *addr
被阅读了。我希望加载from
和to
的下一个值。
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/
答案 0 :(得分:20)
我认为它只发出一条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月补充:)
硬件(处理器)和编译器在缓存方面取得了很大进展,因此使用__builtin_prefetch
似乎在今天(2018年)不太有用。一定要进行基准测试。
答案 1 :(得分:11)
它读取缓存行。缓存行大小可能会有所不同,但在现代CPU上最有可能是64字节。如果您需要读取多个缓存行,请查看prefetch_range
。