C++ 中的一个非常大的 3D 数组
A REALLY huge 3D array in C++
关键是:我正在编写一种愚蠢的程序,它获取手绘声波的 BMP 图像并将其转换为实际声音。它工作正常,但我正在寻找一种将整个图像加载到内存中的好方法。我目前使用 std::vector 加载一个 500 MB 的图像,只是为了在任务管理器中看到该进程分配了太多我的 8GB RAM,以至于它需要额外的分页(停止在 6 GB 左右)。我想这是某种开销...
我的问题是:是否有更节省内存的方法来分配巨大的 3D 数组?是否有任何速度高效的方法来逐字节读取大文件? (我在等待它加载时正在写这篇文章,大约 50 分钟后它是 85%)
编辑
OS 是 64 位 Windows。它甚至超过 6GB,RAM 对它来说太小了,所以 Windows 开始将数组放入分页文件中(我做了一个小百分比指示器,当时分配大约是 80%)。
这是我用于分配的代码
vector <vector<vector<char> > > raster_data; //declaration
raster_data.resize(width);
for(int i=0; i<width; i++)
{
raster_data[i].resize(height);
for(int j=0; j<height; j++)
{
raster_data[i][j].resize(3); //(24bpp=3Bpp)
}
}
所以我不是通过 push_back() 写入数据,而是像普通数组一样访问向量:
raster_data[i][j][k] // in a 3d for loop
你所说的3D数组更多的是包含RGB元素的2D数组,500Mb确实不是'REALLY huge'那些日子
应避免使用 std::vector
仅存储 3 个字节 (char
) 的方法,因为:
std::vector
ifself 消耗了超过 3 个字节(您可以通过检查 sizeof(std::vector<char>)
. 的结果知道多少)
- 您分配的内存碎片化
传统上,对于加载 2D 位图的用例,内存分配在单个块中,然后使用计算索引访问值。
过度简化,这将是这样的:
struct rgb { // you should check that sizeof(rgb) == 3*sizeof(char), just to be sure
char channels[3];
};
std::vector<rgb> raster_data;
raster_data.resize(width*height);
// channel access :
raster_data[j*width+i][k] = ...;
您可以像这样在缓冲区中有效地读取整个文件内容,但是您需要考虑每一行的对齐方式,而且在我的脑海中,我真的不能说它是什么(我相信每一行都在 4 字节边界上对齐)。
如果想了解更多关于在C/C++中处理BMP位图数据,我强烈建议你看一下Handmade Hero,它从一开始就涵盖了这个主题,我相信这一集:https://www.youtube.com/watch?v=ofMJUSchXwo
关键是:我正在编写一种愚蠢的程序,它获取手绘声波的 BMP 图像并将其转换为实际声音。它工作正常,但我正在寻找一种将整个图像加载到内存中的好方法。我目前使用 std::vector 加载一个 500 MB 的图像,只是为了在任务管理器中看到该进程分配了太多我的 8GB RAM,以至于它需要额外的分页(停止在 6 GB 左右)。我想这是某种开销...
我的问题是:是否有更节省内存的方法来分配巨大的 3D 数组?是否有任何速度高效的方法来逐字节读取大文件? (我在等待它加载时正在写这篇文章,大约 50 分钟后它是 85%)
编辑 OS 是 64 位 Windows。它甚至超过 6GB,RAM 对它来说太小了,所以 Windows 开始将数组放入分页文件中(我做了一个小百分比指示器,当时分配大约是 80%)。
这是我用于分配的代码
vector <vector<vector<char> > > raster_data; //declaration
raster_data.resize(width);
for(int i=0; i<width; i++)
{
raster_data[i].resize(height);
for(int j=0; j<height; j++)
{
raster_data[i][j].resize(3); //(24bpp=3Bpp)
}
}
所以我不是通过 push_back() 写入数据,而是像普通数组一样访问向量:
raster_data[i][j][k] // in a 3d for loop
你所说的3D数组更多的是包含RGB元素的2D数组,500Mb确实不是'REALLY huge'那些日子
应避免使用 std::vector
仅存储 3 个字节 (char
) 的方法,因为:
std::vector
ifself 消耗了超过 3 个字节(您可以通过检查sizeof(std::vector<char>)
. 的结果知道多少)
- 您分配的内存碎片化
传统上,对于加载 2D 位图的用例,内存分配在单个块中,然后使用计算索引访问值。
过度简化,这将是这样的:
struct rgb { // you should check that sizeof(rgb) == 3*sizeof(char), just to be sure
char channels[3];
};
std::vector<rgb> raster_data;
raster_data.resize(width*height);
// channel access :
raster_data[j*width+i][k] = ...;
您可以像这样在缓冲区中有效地读取整个文件内容,但是您需要考虑每一行的对齐方式,而且在我的脑海中,我真的不能说它是什么(我相信每一行都在 4 字节边界上对齐)。
如果想了解更多关于在C/C++中处理BMP位图数据,我强烈建议你看一下Handmade Hero,它从一开始就涵盖了这个主题,我相信这一集:https://www.youtube.com/watch?v=ofMJUSchXwo