C++ c++;有效读取每个X字节中的前几个字节
我想从文件的每个X*16字节中读取前16个字节。我写的代码可以工作,但是速度很慢,因为有很多函数调用C++ c++;有效读取每个X字节中的前几个字节,c++,windows,performance,file,bytebuffer,C++,Windows,Performance,File,Bytebuffer,我想从文件的每个X*16字节中读取前16个字节。我写的代码可以工作,但是速度很慢,因为有很多函数调用 std::vector<Vertex> readFile(int maxVertexCount) { std::ifstream in = std::ifstream(fileName, std::ios::binary); in.seekg(0, in.end); int fileLength = in.tellg(); int vertexCoun
std::vector<Vertex> readFile(int maxVertexCount) {
std::ifstream in = std::ifstream(fileName, std::ios::binary);
in.seekg(0, in.end);
int fileLength = in.tellg();
int vertexCount = fileLength / 16;
int stepSize = std::max(1, vertexCount / maxVertexCount);
std::vector<Vertex> vertices;
vertices.reserve(vertexCount / stepSize);
for (int i = 0; i < vertexCount; i += stepSize) {
in.seekg(i * 16, in.beg);
char bytes[16];
in.read(bytes, 16);
vertices.push_back(Vertex(bytes));
}
in.close();
}
std::向量读取文件(int-maxVertexCount){
std::ifstream in=std::ifstream(文件名,std::ios::binary);
in.seekg(0,in.end);
int fileLength=in.tellg();
int vertexCount=fileLength/16;
int stepSize=std::max(1,vertexCount/maxVertexCount);
向量顶点;
顶点保留(顶点计数/步长);
对于(int i=0;i
有人能给我一些建议来提高这段代码的性能吗?不要使用
seek
,我会mmap
整个文件,然后简单地读取所需位置的字节
我不打算为您编写代码,但应该遵循以下原则:
mmap
整个文件顶点
,并推入向量。。。如果由于某种原因您不能使用
映射
,请“大口”将文件读入缓冲区。。。缓冲区大小是X
字节的倍数。继续读取该缓冲区(注意读取了多少字节)。直到到达文件的末尾
您特别想要避免的是一大堆物理I/O操作:磁盘读/写机制的移动。由于这个原因,操作系统喜欢缓冲东西,但它只能猜测应用程序正在尝试做什么,而且可能猜错了。一旦磁盘将读/写磁头定位到正确的磁道(“寻道时间”),它可以在一次旋转中检索整个磁道的数据。但“寻找时间”相对较慢
映射文件,然后非随机地读取映射文件中的数据,显然是最有利的策略,因为现在操作系统确切地知道发生了什么。这可能不是函数调用本身,而是非顺序访问模式,从大文件中拾取小段。即使您只读取16个字节,存储子系统也可能读取(并缓存)更大的块。对于典型的I/O,您的访问模式是致命的 (分析应该显示磁盘访问是否是瓶颈。如果是“许多函数调用”,CPU将是。) 因此,首先,您可以更改此要求吗?
这在所有情况下都是最简单的解决方法 你能少散点吗?例如,不读取顶点0、20、40、…、1000,而是读取顶点0、1、2、3、4、100、101、102、103、104、200、201、202、203、204、…-相同数量的顶点,来自文件的“所有部分” 其次,特定于操作系统的优化
没有可移植的方法来控制操作系统级缓存 一种解决方案是内存映射文件(
CreaterFileMapping
在Windows上,mmap
在Linuxy系统上),正如@Nim所建议的那样。这可以省略一个内存副本,但仍将读取整个文件
Linux帮不了什么忙,但在Windows上,您可以使用以下参数来创建文件:
这基本上意味着你做了缓冲,让你更好地控制发生的缓存,但你不能随意地查找+读取FILE\u FLAG\u NO\u BUFFERING
只需telsl缓存,不存储旧数据FILE\u FLAG\u SEQUENTIAL\u SCAN
最好的选择可能是将交错快照存储在相关文件中 对于特定的
maxVertexCount
,快照可能只是您操作的结果。或多个快照,如mipmapping。其思想是用顺序读取代替分散读取
或者,快照可以交错顺序存储数据。对于128个顶点,您可以按该顺序存储顶点(大致上,注意off by首先,我假设您正在从定义中按值返回向量,即使您发布的代码缺少return语句,因此必须复制向量。通过引用将其传递到方法中,因此不需要复制 您可以使用低级别来阅读,而无需查找:
void readFile( size_t maxVertexCount, std::vector<Vertex> &vertices )
{
struct stat sb;
int fd = std::open( fileName, O_RDONLY );
std::fstat( fd, &sb );
size_t vertexCount = sb.st_size / 16;
size_t stepSize = std::max( 1, vertexCount / maxVertexCount );
vertices.reserve( vertexCount / stepSize );
for ( off_t i = 0; i < vertexCount; i += stepSize)
{
char bytes[ 16 ];
std::pread( fd, bytes, 16, 16 * i );
vertices.push_back( Vertex( bytes ) );
}
std::close( fd );
}
void readFile(大小\u t maxVertexCount,标准::向量和顶点)
{
结构统计某人;
int fd=std::open(仅文件名);
标准:fstat(fd和sb);
尺寸垂直计算=sb.st\U尺寸/16;
大小\u t步长=标准::最大值(1,vertexCount/maxVertexCount);
顶点保留(顶点计数/步长);
对于(off_t i=0;i
您应该能够找出所需的错误处理和头文件
这将利用内核的页面缓存和可能的预读或读取整个文件的速度可能更快,也可能不会更快。谢谢您的回复。这似乎是更好的解决方案,因为由于windows的原因,mine.mmap不是一个选项。我尝试使用ifstream来读取整个文件,但第二步会变慢(整个文件可能高达1 TB)。嗯,您没有真正指定约束条件……无论如何,