使用内存文件
Posted
技术标签:
【中文标题】使用内存文件【英文标题】:Working with in memory file 【发布时间】:2014-09-29 12:41:26 【问题描述】:据我了解,如果我们加载任何文件一次以供读取,则它会按照根据 LRU 算法保留在 RAM 中,直到不会被其他文件交换。
在我的 C 程序 中,我正在加载 124MB 文本文件以读取其内容。理想情况下,一旦我执行它应该在 RAM 中,下次当我很快执行相同的程序时,它应该只从 RAM 中获取。
但这两种情况下的时间都只有15s,与我执行同一个程序的时间无关。
由于缓存大小非常有限,例如 3MB,因此无法放入缓存中。
还有什么其他的方法可以加快程序的执行速度?
更新:
代码链接:
http://webdocs.cs.ualberta.ca/~sajib/cmput606/project/code/svm_classify.c - 此文件包含 main() 类并执行分类工作
http://webdocs.cs.ualberta.ca/~sajib/cmput606/project/code/svm_common.c - 此文件包含用于读取文件和执行分类的功能
【问题讨论】:
不要多次运行您的程序。也许你可以使用循环? 哪个缓存?您是否真的在第一次运行中使用了第二次所需的所有数据,还是跳过了它?另外,你确定第一个是冷跑吗? @KerrekSB:每次用户输入时,我的流程都不同。所以不能把它放在循环中 @Deduplicator:是的,我必须在第一次运行以及每次运行中使用所有数据。因为是SVMrank训练好的分类文件,用来对输入文本进行分类 【参考方案1】:一旦您的文件被第一次读取,在正常配置的操作系统下,所涉及的磁盘页面很可能会被有效缓存。
假设其他进程不需要此内存,第二次读取将比第一次快得多。
作为快速测试,我们生成一个随机文件并计算两次 md5sum(Linux 中的示例):
$ dd if=/dev/urandom of=/tmp/readtest count=124 bs=1M
$ echo 3 > /proc/sys/vm/drop_caches # needs to be run as root
$ time md5sum /tmp/readtest
f788abe8a8d120a87bb293e65e5d50ff /tmp/readtest
real 0m5.706s
user 0m0.332s
sys 0m0.072s
$ time md5sum /tmp/readtest
f788abe8a8d120a87bb293e65e5d50ff /tmp/readtest
real 0m0.295s
user 0m0.268s
sys 0m0.024s
在删除缓存页面后观察巨大的差异。
您可能不欣赏这一点是有原因的:
当您第一次读取文件时,该文件实际上已被缓存(很可能) 此磁盘或分区禁用缓存,或文件系统/设备不支持缓存(极不可能)。【讨论】:
是的,非常感谢这些努力。即使我测试了你的代码。正如您所描述的那样,它确实在起作用。在我的情况下,我什至期待类似的行为,但它让我在过去 3-4 天感到痛苦 这是我正在处理的包hlt.utdallas.edu/~altaf/cherrypicker.html,它在里面使用svmlight.joachims.org svm 分类器。下载后,只有一个命令可以测试它【参考方案2】:在不错的 SSD 上加载一个 120MB 的文件需要不到 1 秒的时间。硬盘需要 2-3 秒。我可以假设您不会大块地读取文件,而是使用标准库中的函数(例如fscanf
或使用fstream
)以小增量读取它。
尝试以大块 (1-16MB) 读取文件并在该缓冲区上进行处理。
如果有大量的 I/O 调用来读取文件,则会因从内核模式到用户模式来回切换以及其他请求 I/O 的进程而导致大量开销。
编辑:
给fscanf
和gets
打了很多电话。尝试将整个文件读取到单个缓冲区并在该缓冲区上工作。使用read
(不是fread
)一次性读取文件。
如果文件太大,将其拆分为 1MB 读取。
编辑2
在函数 read_model
中,将 fscanf
替换为 sscanf
以处理缓冲区。
一次将所有模型读取到文件大小的大缓冲区中。可以使用stat
找到文件大小。而不是使用fgets
使用strtok
迭代缓冲区。后者可用于在迭代时用 NULL 字符替换新行。
如果您不知道这些功能中的任何一个,请尝试使用 Google 搜索 man funcname
。例如。 man strktok
.
【讨论】:
是的,我正在浏览开源代码 4 天。我已经添加了链接。如果你能看一下并提出我的任何建议,我真的很感激 非常感谢,我一遍又一遍地通过代码,我无法找到并决定在哪里以及如何决定读取缓冲区大小(以 1-16mb 为单位)。虽然你已经给出了这么多的细节,如果你指出我会很有帮助 查看更新的答案,如果这没有显着改善,然后运行分析器并查看代码停顿的位置。可能与文件读取无关。【参考方案3】:如果您将文件作为一个整体读取,如果您的操作系统缓存了该文件,该文件将位于 RAM 中。如果在两次运行之间,缓存压力使您的操作系统(以 Linux 内核为例)丢弃了已加载的文件,您的文件将再次从磁盘读取它。
但是,您的程序无法控制文件是否来自缓存。操作系统为您的程序提供文件,无论是来自磁盘还是来自文件缓存,都超出了您的控制范围。
更多信息可以在这篇小文章中找到:Experiments and fun with the Linux disk cache
【讨论】:
以上是关于使用内存文件的主要内容,如果未能解决你的问题,请参考以下文章