我有許多浮點數形式的數據文本文件。我正在尋找用C++讀取它們的最快方法。如果這是最快的,我可以將文件更改爲二進制文件。讀取輸入文件,最快的方式可能嗎?
如果您可以給我提示或轉介給我一個完整解釋的網站,那將是非常好的。我不知道是否有任何圖書館能夠快速完成這項工作。即使有任何開源軟件能夠完成這項工作,那也是有幫助的。
我有許多浮點數形式的數據文本文件。我正在尋找用C++讀取它們的最快方法。如果這是最快的,我可以將文件更改爲二進制文件。讀取輸入文件,最快的方式可能嗎?
如果您可以給我提示或轉介給我一個完整解釋的網站,那將是非常好的。我不知道是否有任何圖書館能夠快速完成這項工作。即使有任何開源軟件能夠完成這項工作,那也是有幫助的。
擁有二進制文件是最快的選擇。不僅可以直接在單個操作(非常快)中以原始istream::read
的陣列讀取它,但是如果操作系統支持它,甚至可以將文件映射到內存中;您可以在Windows上使用open
/mmap
,在Windows上使用CreateFile
/CreateFileMapping
/MapViewOfFile
,甚至可以使用Boost跨平臺解決方案(感謝@Cory Nelson指出)。
快速&骯髒的例子,假設該文件包含了一些float
S的原始表示:
「正常」 改爲:
#include <fstream>
#include <vector>
// ...
// Open the stream
std::ifstream is("input.dat");
// Determine the file length
is.seekg(0, std:ios_base::end);
std::size_t size=is.tellg();
is.seekg(0, std::ios_base::beg);
// Create a vector to store the data
std::vector<float> v(size/sizeof(float));
// Load the data
is.read((char*) &v[0], size);
// Close the file
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](http://www.boost.org/doc/libs/1_47_0/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.mapped_file)提供了跨平臺的內存映射文件。 –
@Cory:呃,不錯,不知道Boost也得到了。 –
如果文件已被緩存,內存映射將會非常快。如果不是,'read'將會勝過它。 –
你瓶頸在I/O中。您希望程序以最少的I/O調用將盡可能多的數據讀入內存。例如,讀取一個fread
的256個數字比一個數字的256個fread
快。
如果可以,請格式化數據文件以匹配目標平臺的內部浮點表示法,或至少與您的程序表示法相匹配。這減少了將文本表示轉換爲內部表示的開銷。
如果可能的話,繞過操作系統並使用DMA控制器讀取文件數據。 DMA芯片承擔了將數據從處理器的肩上讀取到內存中的負擔。
壓縮你的數據文件。數據文件想要位於磁盤上的一組連續的扇區中。這將減少花在尋找物理盤片上不同區域的時間。
您是否編程需求對磁盤資源和處理器的獨佔控制權。阻止所有其他不重要的任務;提高程序執行的優先級。
使用多個緩衝區來保持磁盤驅動器旋轉。花費大量時間等待硬盤加速和減速。您的程序可以處理數據,而其他數據則將數據存儲到緩衝區,從而導致...
多線程。創建一個線程來讀取數據,並在緩衝區不爲空時提醒處理任務。
這些應該讓你忙一會兒。所有其他優化將導致性能收益微不足道。 (如直接訪問硬盤驅動器控制器,將其轉移到您的緩衝區中。)
有趣..... – tomasz
OP有一個文本文件。加速#2,將該文本文件轉換爲二進制文件,將極大地加快速度。按照#1的方式,儘可能多地讀一遍。之後的一切都是肉汁。 –
另一個注意編譯模式。 我試着用1M行解析一個文件。調試模式消耗50secs來解析數據並附加到我的容器。釋放模式消耗的速度至少快十倍,大約4秒。 下面的代碼是在使用istringstream將數據解析爲2D點(,)之前讀取整個文件。
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]);
}
請不要將C++問題標記爲'c'。這只是煩人的。 –