C++ 读取二进制文件的性能

C++ 读取二进制文件的性能,c++,performance,file,optimization,io,C++,Performance,File,Optimization,Io,我有一个程序,从一个非常大的二进制文件(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) {

我有一个程序,从一个非常大的二进制文件(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();
int位置=0;
对于(int i=0;i

问题是,对于一个像一开始那样的大文件,它需要很多时间(约7分钟),而且应该进行优化。如何在更短的时间内读取文件?

因此,存储在内存中的数据结构如下所示:

rgbrgbrgbrgbrgbrgbrgbrgbrgbrgb..............rgb
但是您正在读取的文件的结构如下所示(假设您的代码逻辑正确):

在您的代码中,您正在两者之间进行转换。从根本上说,这将是缓慢的。更重要的是,您选择通过手动查找文件中的任意点来读取文件。这会让事情变得更慢

您可以做的第一件事是简化硬盘读取:

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;
                }
            }
        }
    }
}
这是非常短的,并且可能会超过所有其他方法。但当然,这可能不是你的选择


我还没有测试过这些方法中的任何一种(可能有一两个输入错误),但所有这些方法都应该比您当前所做的更快。

更快的方法是将位图读入缓冲区:

uint8_t buffer[HEIGHT][WIDTH];
const unsigned int bitmap_size_in_bytes = sizeof(buffer);
myFile.read(buffer, bitmap_size_in_bytes);

一种更快的方法是将多个位图读入内存

你是怎么想出那笔生意的?怪不得这么慢。你有没有试过稍微点一下,在一个rgb三元组中寻找一个,然后在一个IO中读取所有3个。正如@BaummitAugen所说,不管怎样,你不必看kg。按顺序访问文件并在
matrixPixel
周围跳跃,而不是试图在文件周围跳跃,这非常、非常、非常有意义。实际上,您应该做的是将所有
pixle
存储在一个平面数组/向量中,然后通过
read
调用一次读取它们。这不是一个聪明的主意。如果它是(比如)通过三个滤镜拍摄的天文图片,并且完整的图像是通过连接“红色”、“绿色”和“蓝色”图像而形成的,那么格式是合理的。第一件事可能会将阅读时间减少到几乎最小。@MartinBonner批量阅读,与第二个和第三个示例一样,将显著降低读取速度。一次读一个字符,即使是按顺序读,也比批量读慢。@MartinBonner谢谢,第一个要快得多。我对第二个版本仍然有一些问题,但是对于写作来说会是一样的吗?
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];
}
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);