dan*_*sto 0 c++ io optimization performance file
我有一个程序从一个非常大的二进制文件(48 MB)读取,然后将数据传递给名为像素的自定义结构矩阵:
struct pixel {
    int r;
    int g;
    int b;
};
Run Code Online (Sandbox Code Playgroud)
打开文件:
ifstream myFile(inputPath, ios::binary);
pixel **matrixPixel;
Run Code Online (Sandbox Code Playgroud)
以这种方式读取文件:
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();
Run Code Online (Sandbox Code Playgroud)
问题是,对于像开头一样的大文件,需要花费很多时间(约7分钟)并且应该进行优化.我怎样才能在更短的时间内从文件中读取?
因此,您存储在内存中的数据结构如下所示:
rgbrgbrgbrgbrgbrgbrgbrgbrgbrgb..............rgb
Run Code Online (Sandbox Code Playgroud)
但是您正在阅读的文件结构如下(假设您的代码逻辑正确):
rrrrrrrrrrrrrrrrrrrrrrrrrrr....
ggggggggggggggggggggggggggg....
bbbbbbbbbbbbbbbbbbbbbbbbbbb....
Run Code Online (Sandbox Code Playgroud)
在你的代码中,你在两者之间进行翻译.从根本上说,这将是缓慢的.而且,你已经选择通过手动搜索文件中的任意点来读取文件.这会让事情变得更加缓慢.
您可以做的第一件事是简化硬盘读取:
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;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
这需要对代码进行最少的更改,并且会加快代码速度,但代码可能仍会很慢.
一种更好的方法,可以增加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];
}
Run Code Online (Sandbox Code Playgroud)
最后的最佳方法是更改二进制文件的格式,因为它看起来格式化的方式是疯狂的(从性能角度来看).如果文件被重新格式化为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);
Run Code Online (Sandbox Code Playgroud)
这非常短,可能会超越所有其他方法.但是,当然,这可能不适合你.
我没有测试任何这些方法(可能有一两个错字),但所有这些方法应该比你目前正在做的更快.