每次读/写有多少次随机/顺序访问
How many random / sequential access per fread / fwrite?
我有以下关于C文件I/o的问题。
在物理级别(硬盘驱动器),假设每个fread(n_blocks, size, length,FILE fp)
操作应该花费1次随机访问第一页(块)和n-1次顺序访问同一缓冲区的下一个块是有效的吗?
我认为这是因为操作系统有如此多的进程,几乎可以肯定其中一个进程也在本地程序的每个fread
之间写入或读取文件,并且通过这种假设硬盘驱动器位于另一个扇区/圆柱体。
可以这样假设吗?
无论你是否这样认为,这都是对现实的过度简化。
第一件事:你似乎认为第三个参数(length
)对应于一些离散的"访问操作"的数量。事实并非如此。fread
所做的只是读取size*length
字节;因此,下面三个调用做完全相同的事情,只要乘法不溢出:
fread(n_blocks, size, length, fp);
fread(n_blocks, size*length, 1, fp);
fread(n_blocks, 1, size*length, fp);
实际上发生的是,fread/fwrite
将从进程内存中的内部缓冲区读写。该缓冲区可以通过setbuf/setvbuf
函数进行控制。当缓冲区满/空时,它们将把读/写转发给操作系统,该操作系统有自己的文件缓存。如果您正在读取并且操作系统无法在缓存中找到文件的部分,那么您的程序将等待,直到实际从驱动器中获取数据。当写入时,数据将被复制到操作系统缓存中并驻留在那里,直到操作系统决定将其写入驱动器,这可能发生在您的程序关闭文件并存在很久之后。反过来,今天的硬盘有自己的内部缓存,操作系统甚至可能不知道。
对于所有实际目的,您不应该关心每个fread/fwrite
调用访问多少驱动器。只要知道C、操作系统和底层硬件将尽其所能以最快的速度提供所请求的数据。但是,请记住,整个堆栈是为顺序访问优化的。因此,请避免在没有充分理由的情况下使用fseek
在文件周围跳跃。
不,它不是。如果文件系统是碎片化的,单个文件的块可能会分散在整个硬盘上。
不,不是。您甚至不能假设fread
将触发物理I/O。你的操作系统有可能对I/O请求做很多事情,包括缓存结果、重新排序和合并(或分割)读(甚至有时写)。
如果有很多I/O正在进行,你也不能指望得到顺序读取,这取决于你使用的缓冲区大小(可能还有I/O流库)。一些操作系统提供了一些方法来"提示"您将按顺序读取文件描述符(或mmap
ed区域),这可能会有所帮助。
从应用程序程序员的角度来看,读取数据块的确切过程是不确定的。这一切都归结为磁盘调度器,它组织来自多个进程的多个请求同时进行的访问操作。有多种算法可以解决这个问题,但过于简单的思考(1次随机搜索,n次顺序搜索)是不现实的。最后,C标准和c++标准都没有明确地定义这样的事情。
正如许多人解释的那样,必须考虑缓存(可能在几个级别上)。
也许你想知道如何从C代码中加速或调整它。这是高度特定于操作系统的
在最近的Linux系统上,您可以使用readahead, madvise(与mmap一起使用)和其他系统调用。
通常,您可以简单地提前读取文件(可能只是使用cat yourfile > /dev/null
),然后您的程序将在Linux上运行得更快。
尝试在一些大文件上运行两次wc
单词计数实用程序。第二次运行通常比第一次运行快得多。
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- CMake-按正确顺序将项目与C运行时对象文件链接
- 函数调用中参数的顺序重要吗
- 为什么 Serial.println(<char[]>);返回随机字符?
- 以随机可重现的顺序生成非重复字节的快速方法
- C/C++ Windows 或 Linux 将随机内存块映射成连续的顺序
- 从容器中获取随机元素,该容器在恒定时间内没有严格的元素顺序
- 编译时随机化结构成员的顺序
- 如何使用 std::shuffle 以随机顺序对具有唯一指针的向量进行洗牌
- 随机顺序的连续数字
- OMP并行以随机顺序写入
- 如何使MPI_Send让处理器按顺序而不是随机发送
- 使用提升 Qi 解析为结构的随机顺序
- 如何从向量中删除随机元素而不重复它们并保持元素顺序?C++
- 以随机顺序接收行时压缩位矩阵
- 以随机顺序迭代数组
- 如何使用双向搜索按字母顺序将随机字符串添加到数组中
- 随机顺序洗牌cv::Mat在OpenCV中
- 每次读/写有多少次随机/顺序访问
- 在c++中以随机顺序显示5个图像