Python 使用mmap时查找缓存未命中

Python 使用mmap时查找缓存未命中,python,linux,mmap,Python,Linux,Mmap,我需要在相当大的文件中执行搜索。搜索操作需要随机访问(想想二进制搜索),为了便于使用和性能,我将mmap文件。搜索算法将页面大小考虑在内,因此每当我需要访问某个内存区域时,我都会尽量充分利用它。因此,有几个参数需要调整。我想找到使我从块设备读取的次数最少的参数 我可以用笔和纸来做这件事,但理论工作只进行到目前为止。实际环境中发生的事情很多,页面缓存也不同,这就更加复杂了。有多个进程访问文件,由于文件上的其他活动,文件系统页面缓存中的某些页面通常可用。(我假设操作系统在使用mmap时意识到这些)

我需要在相当大的文件中执行搜索。搜索操作需要随机访问(想想二进制搜索),为了便于使用和性能,我将
mmap
文件。搜索算法将页面大小考虑在内,因此每当我需要访问某个内存区域时,我都会尽量充分利用它。因此,有几个参数需要调整。我想找到使我从块设备读取的次数最少的参数

我可以用笔和纸来做这件事,但理论工作只进行到目前为止。实际环境中发生的事情很多,页面缓存也不同,这就更加复杂了。有多个进程访问文件,由于文件上的其他活动,文件系统页面缓存中的某些页面通常可用。(我假设操作系统在使用
mmap
时意识到这些)

为了查看我的搜索算法在从块设备读取的块数方面的实际性能,我需要知道在我的
mmap
访问期间发生的页面未命中数

dream com true解决方案是告诉我内存区域的哪些页面已经在缓存中。一个非常好的解决方案是一个函数,它告诉我给定的页面是否在真实内存中。这将使我能够调整参数,甚至可能成为我算法的一部分(“如果这个页面在真实内存中,我们将从中提取一些信息,如果不是,那么我们将阅读另一个页面”)

该系统将在Linux(3系列内核)上运行,因此如果没有操作系统不可知的答案,Linux特定的答案是可以接受的。基准测试将用python编写,但是如果接口只存在于C中,那么我将接受它

示例

让我们创建一个具有固定记录长度的文件,记录中包含排序标识符和一些数据。我们希望提取一些起始位置和结束位置(由标识符定义)之间的数据。简单的解决方案是使用二进制搜索找到起始位置,然后返回所有内容,直到到达结束位置

但是,如果我们需要考虑缓存,情况会有所变化。直接内存访问基本上是免费的,但页面丢失是昂贵的。一个简单的解决方案是使用二进制搜索查找范围内的任何位置。然后可以向后遍历文件,直到到达起始位置。然后遍历文件这听起来很愚蠢,但它可以确保一旦找到范围内的一个点,就不需要加载额外的页面

因此,最重要的是找到范围内的单个位置。二进制搜索是一个很好的选择,但如果我们知道,例如,文件的最后三页或前三页通常都在页面缓存中,我们也应该使用该信息。如果我们知道哪些页面在缓存中,搜索算法可能是m艾德好得多,但即使事后知道我们是否击中或错过了帮助

(实际问题比这要复杂一些,但这也许说明了这一点。)

部分解决方案:

正如JimB在回答中所说,Linux中没有这样的API,这就给我们留下了更通用的评测工具(比如Linux中python的
cProfile
perf stat

我的代码面临的挑战是,我知道大部分时间都会花在内存访问上,最终导致缓存未命中。这很容易,因为它们是代码可能阻塞的唯一点。在代码中,我有一些类似于
b=a[I]
,这可能非常快,也可能非常慢,具体取决于
I

当然,在进程运行期间查看缓存未命中的总数可能有助于进行一些优化,但我确实知道系统的其余部分是否会造成这样的情况,例如文件的第一页或最后一页大部分时间都在缓存中


因此,我将实现关键内存访问(可能错过缓存的访问)的计时,因为系统中运行的几乎所有东西都是I/O限制的(而不是CPU限制的),上下文切换不太可能经常破坏我的计时。这不是一个理想的解决方案,但似乎是最不坏的解决方案。

这确实是需要在程序之外处理的事情。虚拟内存层由内核处理,细节不向进程本身公开。您可以分析您的在其进程中编程,并根据函数调用的时间来估计发生了什么,但要真正了解发生了什么,需要使用特定于操作系统的分析工具


Linux提供了一个很好的工具:
perf stat
命令可能是您了解程序执行情况所需的全部工具。

这正是我所担心的!我试图偷懒,不在程序中添加大量评测代码,但似乎对调用进行计时是最好的选择。
perf
是good,但在这种情况下,我需要实时的每个进程的统计数据(我不知道如何从
perf
中挤出)。无论如何,这是一条很有价值的信息,因为没有API来确定页面是否在物理内存中,谢谢!@DrV:使用python
cProfile
模块(而不是直接在代码中写入计时信息),您可能能够获得很好的评测信息。但是,由于您的模型依赖于以前的运行和/或将数据读入页面缓存的外部进程,因此操作系统级工具是可行的。我在问题中添加了更多信息,以解释为什么通用分析工具在这里似乎有点不足。当然,可能是我的想法不足,在这种情况下,我感谢al我的建议!