Intel和IBM's xlc等编译器可以自动插入数据预取指令。
我有一些代码可以帮助预取,但代价是可读性。也就是说,有一个自然的代码组合,如
void foo(...){ // foo gets called frequently
...
char *myPtr = allocate(medium_size);
memset(myPtr,0,medium_size) // cache misses here. medium_size is ~ 1 cache line
// Miss occurs on first access by memset, but not enough
// data to ameliorate by any hardware prefetching
// triggered by memset. Basically foo() is called a lot
memset引起的缓存未命中的成本可以通过在过程中进一步推进分配并在之后立即发出预取指令来缓解,在它与memset之间有足够的指令以便有时间将数据发送到被带入缓存。在我的情况下,计算medium_size的代码在程序中进一步向上推进时会变得有点混乱,使其可读性降低。
如果编译器可以为我重新安排代码以使预取有价值(可能得到PGO的支持)那么我可以充分利用这两个世界。
到目前为止,似乎Visual Studio仅支持内在函数,即手动放置预取指令。我错了吗?
针对问题的澄清更新:
问:编译器如何改进上面的代码?答:上面的代码只是为了说明所涉及的内容。实际代码更复杂,但归结为分配和存储。读取由memset写入内存时完成。在某些体系结构上,这可能不会触发缓存未命中,但在x86上它显然会(根据vTune)(由下面的markgz回答)。
问:不仅仅使用memset就足够了吗? memset的内存访问模式是高度可预测的,硬件预取机制应该处理它。 答:是的,总的来说这是事实,我在解释更多背景方面做得不好。 包含memset的例程(foo)被非常频繁地调用,并且它是memset的第一个内存访问,它触发了缓存未命中。 memset没有足够的数据来通过预取来改善这种错过,所以在调用memset之前我需要预取。
答案 0 :(得分:0)
是的,您可以使用
void _mm_prefetch(char *,int)