据我了解,如果我们加载任何文件一次以便读取,那么它将保留在RAM中,每个LRU算法 直到不被其他文件交换。
在我的 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 - 此文件包含用于读取文件和执行分类的函数
答案 0 :(得分:3)
首次读取文件后,在正常配置的操作系统下,所涉及的磁盘页面很可能被有效缓存。
假设其他进程不需要此内存,则第二次读取将比第一次读取快。
作为一个快速测试,我们生成一个随机文件并计算两次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
删除缓存页面后观察巨大差异。
你有理由不理解这一点:
答案 1 :(得分:2)
在一个体面的SSD上加载一个120MB的文件应该不到1秒。硬盘驱动器需要2-3秒。我可以假设您没有以大块读取文件,而是使用标准库中的函数(例如fscanf
或使用fstream
)以小增量读取它。
尝试以大块(1-16MB)读取文件并在该缓冲区上进行处理。
如果有大量的I / O调用来读取文件,那么从内核到用户模式以及其他要求I / O的进程来回切换会产生很多开销。
修改强>
很多来自fscanf
和gets
的来电。尝试将整个文件读取到单个缓冲区并处理该缓冲区。使用read
(不是fread
)一次性读取文件。
如果文件太大,请将其拆分为1MB读数。
<强> EDIT2 强>
在函数read_model
中,将fscanf
替换为sscanf
以处理缓冲区。
将所有模型一次性读取到文件大小的大缓冲区。可以使用stat
找到文件大小。而不是使用fgets
使用strtok
迭代缓冲区。后者可用于在迭代它们时用NULL字符替换新行。
如果您不了解这些功能,请尝试使用Google搜索man funcname
。例如。 man strktok
。
答案 2 :(得分:1)
如果您整个读取文件,如果您的操作系统缓存该文件,该文件将在RAM中。如果在两次运行之间,缓存压力使您的操作系统(以Linux内核为例)丢弃加载的文件,则您的文件将再次从磁盘读取它。
但是,您的程序无法控制文件是否来自缓存。操作系统为您的程序提供文件,无论是从磁盘还是文件缓存都在您的控制之外。
在这篇小文章中可以找到更多信息:Experiments and fun with the Linux disk cache