是否有可能在用户空间分配Linux上的不可caching的内存块?

我有一堆缓冲区(25到30)在我的应用程序是相当大的(.5mb)和访问simulataneousley。 更糟糕的是,它们中的数据通常只读取一次,并经常更新(如每秒30次)。 非理想caching使用的完美风暴。

无论如何,我想,如果我可以将一块内存标记为不可caching,这将是很酷的。理论上,这会在caching中留下更多的空间。

那么,他们的方法是在Linux中获得一个标记为不可caching的内存块吗?

Solutions Collecting From Web of "是否有可能在用户空间分配Linux上的不可caching的内存块?"

如何避免使用这样的数据来污染缓存在每个程序员应该知道的关于内存的问题 (PDF) – 这是从Red Hat开发的角度写的,对你来说非常完美。 但是,大部分是跨平台的。

你想要什么叫做“Non-Temporal Access”,并告诉处理器,期望你正在读的值现在不会再需要一段时间了。 处理器然后避免缓存该值。

请参阅上面链接的PDF的第49页。 它使用英特尔固有的做缓存周围的流。

在读取方面,直到最近,处理器都缺乏对使用非时间访问(NTA)预取指令的弱提示的支持。 对于读操作来说,没有等效的写操作,这对于无法缓存的内存(如内存映射I / O)尤其不利。 带有SSE4.1扩展的英特尔引入了NTA负载。 它们使用少量流式加载缓冲区来实现; 每个缓冲区都包含一个缓存行。 给定高速缓存行的第一个movntdqa指令会将高速缓存行加载到缓冲区中,可能会替换另一个高速缓存行。 后续的16字节对齐访问同一个缓存行将从加载缓冲区服务很少的成本。 除非有其他原因,缓存行将不会被加载到缓存中,因此可以加载大量内存而不会污染缓存。 编译器提供了这个指令的一个内在特性:

#include <smmintrin.h> __m128i _mm_stream_load_si128 (__m128i *p); 

这个内在应该被多次使用,以16字节块的地址作为参数传递,直到读取每个缓存行。 只有这样才能启动下一个缓存行。 由于有几个流读缓冲区,所以可能一次从两个内存位置读取数据

如果在读取时缓冲区是通过内存以线性顺序读取的,那对你来说是完美的。 您使用流式读取来执行此操作。 当你想修改它们的时候,缓冲区是按照线性顺序修改的,如果你不希望在同一个线程中重新读取它们,你可以使用流写入来完成。

经常更新的数据实际上是缓存的完美应用。 如上所述,现代的CPU缓存是相当大的,0.5MB可能适合缓存。 更重要的是,虽然读取 – 修改 – 写入未缓存的内存非常慢 – 初始读取必须在内存中阻塞,然后写入操作也必须阻塞内存才能提交。 只是为了增加伤害,CPU可能会通过将数据加载到缓存中来实现无缓存内存,然后立即使缓存线无效 – 从而使您处于一个比以前更糟的位置。

在你尝试以这种方式取代CPU之前,你应该真的应该对整个程序进行基准测试,看看真正的减速在哪里。 像valgrind的cachegrind这样的现代分析器可以测量缓存未命中情况,所以你可以发现这是否是减速的重要来源。

另一方面,更实际的一点是,如果你每秒处理30个RMWs,最糟糕的情况是大约1920个字节的缓存足迹。 这只是现代Core 2处理器的L1尺寸的1/16,很可能会在系统的一般噪声中丢失。 所以不要太担心:)

也就是说,如果“同时访问”意味着“同时由多个线程访问”,请注意CPU之间弹跳的高速缓存行。 这不会被未缓存的RAM所帮助 – 如果有的话会更糟糕,因为数据每次都必须一路回到物理RAM,而不是可能通过更快的CPU间总线 – 唯一的办法为了避免这个问题,最大限度地减少访问共享数据的频率。 有关详细信息,请参阅http://www.ddj.com/hpc-high-performance-computing/217500206

您可能还想查看处理器关联性,以减少高速缓存抖动。

在某些处理器体系结构中,有一些特殊指令可用于将某些缓存行标记为禁用状态。 但是,这些通常是架构特定的,并取决于一些汇编指令。 所以,我建议你参考处理器体系结构文档,并找出如何组装。 然后可以使用GCC的内联汇编来激活它。 这会让性能很糟糕。

PS:如果可以的话,你可能想要想一个不同的方式来处理数据?