C++ 以最快的方式读取输入文件?
我有许多浮点数形式的数据文本文件。我正在寻找最快的方式阅读他们在C++中。如果速度最快,我可以将文件更改为二进制文件C++ 以最快的方式读取输入文件?,c++,input,binary,C++,Input,Binary,我有许多浮点数形式的数据文本文件。我正在寻找最快的方式阅读他们在C++中。如果速度最快,我可以将文件更改为二进制文件 如果你能给我一个提示或者让我去一个有完整解释的网站,那就太好了。我不知道是否有图书馆能很快完成这项工作。即使有任何开源软件可以完成这项工作,这也会很有帮助。拥有二进制文件是最快的选择。您不仅可以使用原始istream::read在一个数组中直接读取它(非常快),而且如果您的操作系统支持,您甚至可以在内存中映射文件;您可以在POSIX系统上使用open/mmap,在Windows上
如果你能给我一个提示或者让我去一个有完整解释的网站,那就太好了。我不知道是否有图书馆能很快完成这项工作。即使有任何开源软件可以完成这项工作,这也会很有帮助。拥有二进制文件是最快的选择。您不仅可以使用原始
istream::read
在一个数组中直接读取它(非常快),而且如果您的操作系统支持,您甚至可以在内存中映射文件;您可以在POSIX系统上使用open
/mmap
,在Windows上使用CreateFile
/CreateFileMapping
/MapViewOfFile
,甚至可以使用Boost跨平台解决方案(感谢@Cory Nelson指出这一点)
快速脏示例,假设文件包含一些float
s的原始表示:
“正常”改为:
#包括
#包括
// ...
//开河
std::ifstream是(“input.dat”);
//确定文件长度
is.seekg(0,std::ios\u base::end);
std::size\u t size=is.tellg();
is.seekg(0,std::ios\u base::beg);
//创建一个向量来存储数据
标准::向量v(大小/大小(浮动));
//加载数据
is.read((char*)&v[0],size);
//关闭文件
is.close();
使用共享内存:
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
using boost::interprocess;
// ....
// Create the file mapping
file_mapping fm("input.dat", read_only);
// Map the file in memory
mapped_region region(fm, read_only);
// Get the address where the file has been mapped
float * addr = (float *)region.get_address();
std::size_t elements = region.get_size()/sizeof(float);
#包括
#包括
使用boost::interprocess;
// ....
//创建文件映射
文件映射fm(“input.dat”,只读);
//将文件映射到内存中
映射的_区域(fm,只读);
//获取映射文件的地址
float*addr=(float*)区域。获取地址();
std::size\u t elements=region.get\u size()/sizeof(float);
您的瓶颈在于I/O。您希望程序以最少的I/O调用将尽可能多的数据读入内存。例如,用一个fread
读取256个数字比用一个数字读取256个fread
快
如果可以,请格式化数据文件以匹配目标平台的内部浮点表示形式,或至少匹配程序的表示形式。这减少了将文本表示转换为内部表示的开销
如果可能,绕过操作系统,使用DMA控制器读取文件数据。DMA芯片将数据读入存储器的负担从处理器的肩上卸下
压缩数据文件。数据文件希望位于磁盘上一组连续的扇区中。这将减少寻找物理磁盘上不同区域所花费的时间
您的程序是否要求独占控制磁盘资源和处理器。阻止所有其他不重要的任务;提高程序执行的优先级
使用多个缓冲区保持磁盘驱动器旋转。大部分时间都花在等待硬盘加速和减速上。您的程序可能正在处理数据,而其他程序正在将数据存储到缓冲区中,这会导致
多线程。创建一个线程来读取数据,并在缓冲区不为空时通知处理任务
这些会让你忙上一段时间。所有其他优化都会带来微不足道的性能提升。(例如,直接访问硬盘驱动器控制器以传输到某个缓冲区。)另一个注意事项是编译模式。 我试着解析一个有一百万行的文件。调试模式花费50秒来解析数据并附加到我的容器中。释放模式消耗的速度至少快十倍,约4秒。 下面的代码是在使用istringstream将数据解析为2D点(,)之前读取整个文件 _数据中的向量; 字符串原始数据; 国际单项体育联合会; 打开(_file_in.c_str(),ios::binary); 如果seekg(0,ios::end); 长长度=ifs.tellg(); 如果seekg(0,ios::beg); 字符*缓冲区; 缓冲区=新字符[长度]; 如果读取(缓冲区、长度); 原始数据=缓冲区; ifs.close(); 删除[]缓冲区;
cout提供跨平台的内存映射文件。@Cory:嗯,很好,我不知道Boost也有这个功能。如果文件已经缓存,内存映射会非常快。如果不是的话,
read
会打败它。@yi_H:我不认为mmap
会比read
慢。我不知道这是否有帮助,但我已经用“正常读取”和“共享内存读取”进行了读取1000万浮点数的测试。使用O3优化,正常读取需要185 ms,boost读取需要328 ms。O3将正常读取速度提高100%,但不会改变提升读取速度。OP有一个文本文件。加速#2,将文本文件转换为二进制文件,将大大加快速度。然后#1,一口气读尽可能多的书。之后的一切都是肉汁。
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
using boost::interprocess;
// ....
// Create the file mapping
file_mapping fm("input.dat", read_only);
// Map the file in memory
mapped_region region(fm, read_only);
// Get the address where the file has been mapped
float * addr = (float *)region.get_address();
std::size_t elements = region.get_size()/sizeof(float);
vector <float> in_data;
string raw_data;
ifstream ifs;
ifs.open(_file_in.c_str(), ios::binary);
ifs.seekg(0, ios::end);
long length = ifs.tellg();
ifs.seekg(0, ios::beg);
char * buffer;
buffer = new char[length];
ifs.read(buffer, length);
raw_data = buffer;
ifs.close();
delete[]buffer;
cout << "Size: " << raw_data.length()/1024/1024.0 << "Mb" << endl;
istringstream _sstr(raw_data);
string _line;
while (getline(_sstr, _line)){
istringstream _ss(_line);
vector <float> record;
//maybe using boost/Tokenizer is a good idea ...
while (_ss)
{
string s;
if (!getline(_ss, s, ',')) break;
record.push_back(atof(s.c_str()));
}
in_data.push_back(record[0]);
}