如何禁用某些内存区域的cpu缓存?

时间:2015-12-23 00:49:42

标签: c linux caching

我在维基百科上读到,禁用cpu-cache可以提高性能:

  

将一些内存范围标记为不可缓存可以通过避免缓存很少重新访问的内存区域来提高性能。

当我用谷歌搜索如何在Linux上使用c时,我没有找到任何东西。并不是我真的需要这个功能,但我还是有兴趣。

你知道有哪些项目使用这种优化吗?

编辑:我为x86_64编程

2 个答案:

答案 0 :(得分:6)

关于非缓存的评论并不意味着您认为它意味着什么,以及它在何处使用,它通常不是用户可访问的功能。也就是说,CPU缓存控制通常是特权操作。

那说......

- 可以构建一个普通的用户程序,其功能的属性是热的"或者"冷"让编译器告诉加载器以最有效利用缓存的方式对函数进行分组。

- 一个普通的程序可以使用linux中的madvise()函数来告诉分页函数各种各样的事情,包括刚刚使用的内存很快就会再次使用的事实。

- 内核本身在后来的内核中使用Memory Type Range Regesters(mtrr)和Page Attribute Table(pat)标志来告诉硬件特定的内存范围(例如内存映射显示缓冲区,以及各种内存)不要缓存PCI总线的部分内容。

"普通数据™"例如,您可能在任何C程序中使用基本上永远不会从标记其任何数据而不是缓存中受益。非缓存数据所享有的性能改进是随后缺少内存映射设备和显示缓冲区几乎不断需要的各种缓存 - 刷新和内存屏障操作。例如,在内存映射设备上放置缓存需要在每次读取之前使用cache invalidate命令,并在每次写入之后执行缓存强制写入命令,以确保读取和写入在所需的确切时刻发生。这会导致毒害"缓存使用率,以最不友好和无益的方式使用并立即丢弃缓存行(物理上有限的资源)。

在极少数情况下,您编写的程序可以访问其中一个缓存有害区域 - 例如,如果您在Linux系统上编写了部分X显示服务器 - 内核已经设置了寄存器设备和非缓存行为对您来说是透明的。

除了各种madvise()类型的使用之外,实际上没有时间让您的正常应用程序级别程序能够将变量标记为对缓存有害。

即便如此,案例是你可以获得任何的好处是如此罕见,以至于如果你真的碰到一个,问题集将包括需求和方法作为一部分你的研究和你已经被告知如何以及为什么这么明确地你不需要提出这个问题。

再次回到相同的例子,如果您正在编写必要的驱动程序,当您在显示适配器硬件或PCI总线上读取时,各种标志和技术本来就是记录并在硬件指南中进行了讨论。

有很多方法可以通过英特尔平台上的CLCLEAR指令等方式从用户空间中取出缓存弹出等。这些技术可以提高一般性能。

由于它是Linux系统上的特权操作,因此可以编写一个内核驱动程序,该驱动程序获取并将内存区域标记为不可缓存,然后让您将其映射到应用程序中。但是对这样一个地区的需求是如此罕见,而且很可能被误用,以至于没有一种正常的方法来实现它。

那你怎么做的?你不是,至少不是你今天的那个人。当您成为具有多线程代码和数据同步问题的亲密专业知识的内核驱动程序编写者时,您将知道如何做到这一点,并且此时您将知道为什么不这样做'我想除了作为最后的手段。

TL; DR ::由于linux使用和管理数据和代码的方式,将普通应用程序的任何部分标记为不可缓存,并且不会导致比保存更多的心碎,从来没有任何好处。因此,没有非特权的API可以做到这一点。

P.S。此外,有人已经指出了导致本文http://lwn.net/Articles/255364/的内容,其中介绍了使程序非常友好缓存的方法,以及一些可以非常便宜地执行缓存绕过操作的方法。例如,memset()的使用倾向于在设置内存时围绕缓存,并且一些操作可以"流过"缓存。这与你提出的问题不同,但是一旦你理解了所有这篇文章,你就会更好地理解为什么将内存区域标记为无法访问通常,正如绝地所说,不是你正在寻找的解决方案。

答案 1 :(得分:0)

最近,我需要在缓存繁重的多线程应用程序中试验未缓存的内存。

我想出了这个kernel module,它允许将未缓存的内存映射到用户空间。

用户进程通过调用模块的字符设备上的mmap()来请求未缓存的内存(请参阅测试目录以获取演示)。

What every programmer should know about memory确实是必读的!