Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 以最快的方式读取输入文件?_C++_Input_Binary - Fatal编程技术网

C++ 以最快的方式读取输入文件?

C++ 以最快的方式读取输入文件?,c++,input,binary,C++,Input,Binary,我有许多浮点数形式的数据文本文件。我正在寻找最快的方式阅读他们在C++中。如果速度最快,我可以将文件更改为二进制文件 如果你能给我一个提示或者让我去一个有完整解释的网站,那就太好了。我不知道是否有图书馆能很快完成这项工作。即使有任何开源软件可以完成这项工作,这也会很有帮助。拥有二进制文件是最快的选择。您不仅可以使用原始istream::read在一个数组中直接读取它(非常快),而且如果您的操作系统支持,您甚至可以在内存中映射文件;您可以在POSIX系统上使用open/mmap,在Windows上

我有许多浮点数形式的数据文本文件。我正在寻找最快的方式阅读他们在C++中。如果速度最快,我可以将文件更改为二进制文件


如果你能给我一个提示或者让我去一个有完整解释的网站,那就太好了。我不知道是否有图书馆能很快完成这项工作。即使有任何开源软件可以完成这项工作,这也会很有帮助。

拥有二进制文件是最快的选择。您不仅可以使用原始
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]);
}