在c和c ++中请求内存缓存

时间:2018-02-15 18:19:59

标签: c++ c caching

我有一个涉及大量已分配实体的程序。我还没有决定它们是连续的内存还是更加链接的列表格式。

这些实体需要尽可能多地根据我将调用公共变量的一块内存进行更新。

通过这种方式,项目的主要代码如下所示

for (entity in entities) {
 //Use common variables to update this entity
}

如果我能够以某种方式影响硬件以尽可能地将全局变量存储在最快的缓存上,那将非常好,以便可以经常读取和写入。

在c或c ++中是否存在影响记忆力的最佳方式?即使没有明确的方法,有没有办法增加公共变量插入并保留在缓存中的概率?

如果我的实体是链接列表而不是连续的内存块,我的技术需要如何改变?

BTW我不确定每个实体的大小和常见变量。如果我不得不猜测我会假设公共变量大约为1.2千字节,每个实体大约为.72千字节但在最终程序中可​​能会增长或缩小

1 个答案:

答案 0 :(得分:0)

  

在c或c ++中是否存在一种影响记忆力的原始方式?

如果您使用GCC / CLANG,则有__builtin_prefetch()。如果不是,您可以尝试_mm_prefetch()或直接汇编代码。对于x86体系结构,有一条PREFETCHx指令。这是一个例子:

void prefetch(void *p)
{
    asm volatile ("prefetcht0 %[p]" : : [p] "m" (*(char *)p));
}

查看Compiler Explorer.

  

如果我的实体是链接列表而不是连续的内存块,我的技术需要如何改变?

您可以尝试使用预取技术来加速链接列表遍历,但通常会有一些注意事项:

  1. 预取是一个异步CPU指令,即我们必须在下一个块之后的下一个或下一个预取,然后开始处理当前的内存块。因此,一旦我们完成了当前的块,下一个块将在CPU缓存中。

  2. 由于第1项,在发出的PREFETCHx指令和缓存中实际存在的数据之间存在未指定且与平台相关的延迟。基本上这意味着一些计算机预取下一个内存块会使进程加速2次,而在其他计算机上它不会产生任何影响甚至降低性能。

  3. 预取适用于缓存行,对于x86架构,它是64字节。如果内存块大于缓存行,我们应该考虑预取memory chunk + CACHE_LINE_SIZE地址。

  4. 总的来说,现代CPU有硬件预取器,预测器,可以推测性地执行代码等等。所以这种手动预取技术可以榨取一些性能,但我担心这也可能只是浪费时间。当所有其他技术(如更好的算法,更好的内存布局等)已经完成时,请将此技术视为最后的优化。