led*_*kol 8 c++ sorting performance file buffering
在我的应用程序中,我正在尝试合并已排序的文件(当然保持它们排序),因此我必须遍历两个文件中的每个元素以将最小值写入第三个.这对大文件来说非常慢,只要我没有看到任何其他选择(迭代必须完成)我正在尝试优化文件加载.我可以使用一些RAM,我可以用它来缓冲.我的意思是不是每次读取两个文件中的4个字节,而是每次读取100Mb之类的东西,然后使用该缓冲区,直到缓冲区中没有元素,然后我将再次重新填充缓冲区.但我想ifstream已经这样做了,它会给我更多的表现吗?有什么理由吗?如果fstream有,也许我可以改变那个缓冲区的大小?
添加
我当前的代码看起来像那样(伪代码)
// this is done in loop
int i1 = input1.read_integer();
int i2 = input2.read_integer();
if (!input1.eof() && !input2.eof())
{
if (i1 < i2)
{
output.write(i1);
input2.seek_back(sizeof(int));
} else
input1.seek_back(sizeof(int));
output.write(i2);
}
} else {
if (input1.eof())
output.write(i2);
else if (input2.eof())
output.write(i1);
}
Run Code Online (Sandbox Code Playgroud)
我不喜欢的是
你能建议改进吗?
谢谢.
如果不进入关于流缓冲区的讨论,您可以seek_back通过执行以下操作来摆脱并通常使代码更简单:
using namespace std;
merge(istream_iterator<int>(file1), istream_iterator<int>(),
istream_iterator<int>(file2), istream_iterator<int>(),
ostream_iterator<int>(cout));
Run Code Online (Sandbox Code Playgroud)
添加了二进制功能
#include <algorithm>
#include <iterator>
#include <fstream>
#include <iostream>
struct BinInt
{
int value;
operator int() const { return value; }
friend std::istream& operator>>(std::istream& stream, BinInt& data)
{
return stream.read(reinterpret_cast<char*>(&data.value),sizeof(int));
}
};
int main()
{
std::ifstream file1("f1.txt");
std::ifstream file2("f2.txt");
std::merge(std::istream_iterator<BinInt>(file1), std::istream_iterator<BinInt>(),
std::istream_iterator<BinInt>(file2), std::istream_iterator<BinInt>(),
std::ostream_iterator<int>(std::cout));
}
Run Code Online (Sandbox Code Playgroud)
除非您的数据有一些非常特殊的内容,否则您不太可能改进 std::fstream 对象中内置的缓冲。
std::fstream 对象被设计为对于通用文件访问非常有效。听起来您并没有通过一次访问 4 个字节的数据来执行任何特殊操作。您始终可以分析代码以查看代码中实际时间花费在哪里。
也许如果您与我们分享代码,我们可能会发现一些严重的低效率问题。
我不喜欢你的算法。在流上向后和向前查找可能很困难,尤其是当数字超出缓冲区边界时。我每次循环时只会读取一个数字。
试试这个:
注意:这不是最佳的(它假设数字的流输入(而你的看起来是二进制的))但我相信你可以使用它作为起点。
#include <fstream>
#include <iostream>
// Return the current val (that was the smaller value)
// and replace it with the next value in the stream.
int getNext(int& val, std::istream& str)
{
int result = val;
str >> val;
return result;
}
int main()
{
std::ifstream f1("f1.txt");
std::ifstream f2("f2.txt");
std::ofstream re("result");
int v1;
int v2;
f1 >> v1;
f2 >> v2;
// While there are values in both stream
// Output one value and replace it using getNext()
while(f1 && f2)
{
re << (v1 < v2)? getNext(v1, f1) : getNext(v2, f2);
}
// At this point one (or both) stream(s) is(are) empty.
// So dump the other stream.
for(;f1;f1 >> v1)
{
// Note if the stream is at the end it will
// never enter the loop
re << v1;
}
for(;f2;f2 >> v2)
{
re << v2;
}
}
Run Code Online (Sandbox Code Playgroud)