C++ 使用STL将大型STL向量写入文件的最快方法
我有一个较大的字符向量(10^9个元素),我想知道将这种向量写入文件的最快方法是什么。到目前为止,我一直在使用下一个代码:C++ 使用STL将大型STL向量写入文件的最快方法,c++,stl,C++,Stl,我有一个较大的字符向量(10^9个元素),我想知道将这种向量写入文件的最快方法是什么。到目前为止,我一直在使用下一个代码: vector<char> vs; // ... Fill vector with data ofstream outfile("nanocube.txt", ios::out | ios::binary); ostream_iterator<char> oi(outfile, '\0'); copy(vs.begin(), vs.end(), oi)
vector<char> vs;
// ... Fill vector with data
ofstream outfile("nanocube.txt", ios::out | ios::binary);
ostream_iterator<char> oi(outfile, '\0');
copy(vs.begin(), vs.end(), oi);
向量vs;
// ... 用数据填充向量
流输出文件(“nanocube.txt”,ios::out | ios::binary);
ostream_迭代器oi(输出文件,'\0');
复制(vs.开始(),vs.结束(),oi);
对于这段代码,将所有数据写入文件大约需要两分钟。实际的问题是:“我可以使用STL和如何使它更快吗?”对于
ostream\u迭代器的构造函数,您的第二个参数有一个轻微的概念错误。如果您不需要分隔符,它应该是NULL pointer(不过,幸运的是,这将被隐式地视为空分隔符),或者应该忽略第二个参数
但是,这意味着在写入每个字符后,代码需要检查指定分隔符的指针(这可能会有点低效)
我想,如果你想使用迭代器,也许你可以试试ostreambuf\u迭代器
其他选项可能包括使用write()方法(如果它可以处理如此大的输出,或者可能以块的形式输出),或者使用特定于操作系统的输出函数。对其使用write方法,它毕竟在ram中,并且您有连续的内存。。最快,但以后需要灵活性?丢失内置缓冲、提示顺序i/o、丢失迭代器/实用程序的隐藏内容、避免使用boost::asio时的streambuf。由于要写入大量数据(~1GB),您应该直接写入输出流,而不是使用输出迭代器。因为向量中的数据是连续存储的,所以这将起作用,并且应该快得多
ofstream outfile("nanocube.txt", ios::out | ios::binary);
outfile.write(&vs[0], vs.size());
因为您的数据在内存中是连续的(正如Charles所说),所以您可以使用低级I/O。在Unix或Linux上,您可以写入文件描述符。在Windows XP上,使用文件句柄。(在XP上有点棘手,但在MSDN中有很好的记录。)
XP在缓冲方面有点滑稽。如果将1GB块写入句柄,速度将比将写入拆分为更小的传输大小(在循环中)慢。我发现256KB的写入是最有效的。一旦你写了循环,你就可以玩这个游戏,看看什么是最快的传输大小。好的,我用for循环写了方法实现,每次迭代写256KB的数据块(正如Rob建议的),结果是16秒,所以问题解决了。这是我拙劣的实现,请随意评论:
void writeCubeToFile(const vector<char> &vs)
{
const unsigned int blocksize = 262144;
unsigned long blocks = distance(vs.begin(), vs.end()) / blocksize;
ofstream outfile("nanocube.txt", ios::out | ios::binary);
for(unsigned long i = 0; i <= blocks; i++)
{
unsigned long position = blocksize * i;
if(blocksize > distance(vs.begin() + position, vs.end())) outfile.write(&*(vs.begin() + position), distance(vs.begin() + position, vs.end()));
else outfile.write(&*(vs.begin() + position), blocksize);
}
outfile.write("\0", 1);
outfile.close();
}
void writecutofile(常量向量&vs)
{
const unsigned int blocksize=262144;
无符号长块=距离(vs.begin()、vs.end())/blocksize;
流输出文件(“nanocube.txt”,ios::out | ios::binary);
对于(无符号长i=0;i距离(vs.begin()+位置,vs.end()))输出文件写入(&*(vs.begin()+位置),距离(vs.begin()+位置,vs.end());
else outfile.write(&*(vs.begin()+位置),blocksize);
}
输出文件。写入(“\0”,1);
outfile.close();
}
谢谢大家。如果您有其他结构,此方法仍然有效
例如:
typedef std::pair<int,int> STL_Edge;
vector<STL_Edge> v;
void write_file(const char * path){
ofstream outfile(path, ios::out | ios::binary);
outfile.write((const char *)&v.front(), v.size()*sizeof(STL_Edge));
}
void read_file(const char * path,int reserveSpaceForEntries){
ifstream infile(path, ios::in | ios::binary);
v.resize(reserveSpaceForEntries);
infile.read((char *)&v.front(), v.size()*sizeof(STL_Edge));
}
typedef std::对STL_边;
向量v;
无效写入文件(常量字符*路径){
流输出文件(路径,ios::out | ios::binary);
outfile.write((const char*)&v.front(),v.size()*sizeof(STL_Edge));
}
无效读取文件(const char*path,int reservespace forentries){
ifstream infle(路径,ios::in | ios::binary);
v、 调整大小(reserveSpaceForEntries);
填充读取((char*)和v.front(),v.size()*sizeof(STL_边缘));
}
您可以尝试创建内存映射文件,然后使用memcpy将向量复制到内存映射文件,而不是通过文件i/o方法进行写入。我刚刚阅读了Meyer的“有效STL”一节,其中提到了[io]streambuf_迭代器
类。非常适合这个!Thnx用于校正。我是在没有深入了解的情况下从某个地方复制粘贴的。我忘了说我正在尝试使事情独立于平台,因此不存在特定于操作系统的问题,但还是thnx。在后台进行写入时,您还想做其他处理吗?如果是这样,请使用重叠I/O传递vs.data()作为缓冲区,vs.size()作为Charles Salvia指定的要写入的字节数。我想知道为什么outfile.write(reinterpret_cast(&(vs)),vs.size()*sizeof(T))代码>不工作?