读取二进制文件的性能
Performance reading binary files
我有一个程序,从一个非常大的二进制文件(48 MB)中读取数据,然后将数据传递给一个名为pixel的自定义结构矩阵:
struct pixel {
int r;
int g;
int b;
};
打开文件:
ifstream myFile(inputPath, ios::binary);
pixel **matrixPixel;
文件的读取是这样完成的:
int position = 0;
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
if (!myFile.eof()) {
myFile.seekg(position, ios::beg);
myFile.read((char *) &matrixPixel[i][j].r, 1); // red byte
myFile.seekg(position + HEIGHT * WIDTH, ios::beg);
myFile.read((char *) &matrixPixel[i][j].g, 1); // green byte
myFile.seekg(position + HEIGHT * WIDTH * 2, ios::beg);
myFile.read((char *) &matrixPixel[i][j].b, 1); // blue byte
++position;
}
}
}
myFile.close();
问题是,对于像开头这样的大文件,它需要花费很多时间(~7分钟),并且应该进行优化。我怎样才能在更短的时间内读取文件?
所以,你存储在内存中的数据结构是这样的:
rgbrgbrgbrgbrgbrgbrgbrgbrgbrgb..............rgb
但是你正在读取的文件结构看起来是这样的(假设你的代码逻辑是正确的):
rrrrrrrrrrrrrrrrrrrrrrrrrrr....
ggggggggggggggggggggggggggg....
bbbbbbbbbbbbbbbbbbbbbbbbbbb....
在你的代码中,你在两者之间进行转换。从根本上说,这将是缓慢的。更重要的是,您选择通过手动查找文件中的任意点来读取文件。这会让事情变得更慢。
你可以做的第一件事是简化硬盘读取:
for(int channel = 0; channel < 3; channel++) {
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
if (!myFile.eof()) {
switch(channel) {
case 0: myFile.read((char *) &matrixPixel[i][j].r, 1); break;
case 1: myFile.read((char *) &matrixPixel[i][j].g, 1); break;
case 2: myFile.read((char *) &matrixPixel[i][j].b, 1); break;
}
}
}
}
}
这需要对代码进行最少的更改,并且会加快代码的速度,但代码可能仍然很慢。
一个更好的方法,可以增加CPU的使用,但显著减少硬盘的使用(在绝大多数应用程序中,这将导致加速),将像这样存储数据:
std::vector<unsigned char> reds(WIDTH * HEIGHT);
std::vector<unsigned char> greens(WIDTH * HEIGHT);
std::vector<unsigned char> blues(WIDTH * HEIGHT);
myFile.read(reds.data(), WIDTH * HEIGHT); //Stream can be checked for errors resulting from EOF or other issues.
myFile.read(greens.data(), WIDTH * HEIGHT);
myFile.read(blues.data(), WIDTH * HEIGHT);
std::vector<pixel> pixels(WIDTH * HEIGHT);
for(size_t index = 0; index < WIDTH * HEIGHT; index++) {
pixels[index].r = reds[index];
pixels[index].g = greens[index];
pixels[index].b = blues[index];
}
最后,也是最好的方法是更改二进制文件的格式化方式,因为它的格式化方式看起来是疯狂的(从性能的角度来看)。如果将文件重新格式化为rgbrgbrgbrgbrgb
样式(这在行业中是更标准的),那么您的代码就变成这样:
struct pixel {
unsigned char red, green, blue;
}; //You'll never read values above 255 when doing byte-length color values.
std::vector<pixel> pixels(WIDTH * HEIGHT);
myFile.read(reinterpret_cast<char*>(pixels.data()), WIDTH * HEIGHT * 3);
这是非常短的,并且可能会优于所有其他方法。当然,这可能不是你的选择。
我还没有测试过这些方法中的任何一个(可能有一两个错别字),但是所有这些方法都应该比你现在做的要快。
更快的方法是将位图读入缓冲区:
uint8_t buffer[HEIGHT][WIDTH];
const unsigned int bitmap_size_in_bytes = sizeof(buffer);
myFile.read(buffer, bitmap_size_in_bytes);
一种更快的方法是将多个位图读入内存。
相关文章:
- 正在读取二进制文件(is_open)
- 在C++中将类(带有Vector成员)保存为二进制文件
- 如何从二进制文件中读取字符串
- 保存/加载大量短数组到二进制文件
- 从二进制文件中读取整数数组
- Android 在编译二进制文件时重建静态库
- 在 C++ 中将双精度变量写入二进制文件
- clang 的 libFuzzer 可以在同一二进制文件中测试超过 1 个 API 吗?
- C++:实际上不是从二进制文件中读取
- 如何从二进制文件中的给定符号中获取调用程序图
- 将内部带有矢量的结构保存/读取到二进制文件中
- 编译多个C++文件.调用二进制文件以运行代码
- 如何使用位字段将数据从二进制文件复制到结构中?
- uint8_t同一二进制文件的不同十进制值
- C++单个生成文件多个二进制文件
- 尝试将数字写入二进制文件时引发异常
- C++中读/写二进制文件
- 如何忽略某些二进制文件的执行?
- MPI 二进制文件 I/O 基本功能和性能问题
- 读取二进制文件的性能