【问题标题】:Reading hdf5 into c++ with memory problems将 hdf5 读入 c++ 内存问题
【发布时间】:2013-06-09 05:12:42
【问题描述】:

我正在将我用python开发的代码重写为c++,主要是为了提高速度;同时也希望能在这门语言中获得更多的经验。我还计划使用 openMP 将此代码并行化到共享 204GB 内存的 48 个内核上。

我正在编写的程序很简单,我导入了一个 3D 的 hdf5 文件: A[T][X][E],其中 T 与模拟的每个时间步长相关联,X 表示测量场的位置,E(0:2) 表示 x,y,z 中的电场。
A 中的每个元素都是双精度数,bin 大小跨度为:A[15000][80][3]。

我遇到的第一个问题是将这个“大”h5 文件输入到一个数组中,并且在继续之前希望获得专业意见。我的第一次尝试:

...
#define RANK  3
#define DIM1  15001
#define DIM2  80
#define DIM3  3

using namespace std;
int main (void)
{
//  Define HDF5 variables for opening file. 
hid_t   file1, dataset1;
double bufnew[DIM1][DIM2][DIM3];
herr_t ret;
uint  i, j, k;

file1 = H5Fopen (FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
dataset1 = H5Dopen (file1, "EFieldOnLine", H5P_DEFAULT);
ret = H5Dread (dataset1, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL,
                H5P_DEFAULT, bufnew);

cout << "Let's try dumping 0->100 elements" << endl;
for(i=1; i < 100; i++) cout << bufnew[i][20][2] << endl;
...

这会导致数组声明出现分段错误。我的下一步是使用 3D 数组(新)或 3D 矢量。然而,我看到了很多反对这些方法的争论,更重要的是,我只需要 E 的一个分量,即我想重塑 A[T][X][E] -> B[T][X] 为比如说,E 的 x 分量。

很抱歉这篇冗长的文章,但我想尽可能清楚,并想再次强调,我有兴趣学习如何编写最快、最有效的代码。 感谢您的所有建议、时间和智慧。

【问题讨论】:

  • 很可能bufnew 对于您可能需要动态分配它的堆栈来说太大了。

标签: c++ multidimensional-array hdf5


【解决方案1】:

将数组定义为局部变量意味着将其分配到堆栈上。堆栈通常被限制为几兆字节,堆栈溢出肯定会导致段错误。大型数据结构应在堆中动态分配(使用new 运算符)或静态分配(当定义为全局变量时)。

我不建议为这些维度制作向量的向量。

相反,创建一个一维数组来存储所有值

double *bufnew = new double[DIM1*DIM2*DIM3];

并使用以下公式访问它以计算给定 3D 项目的线性位置

bufnew[(T*DIM2+X)*DIM3+E] = ... ; // bufnew[T][X][E]

应该没问题。

【讨论】:

  • 我看到的唯一问题是函数:H5Dread (dataset1, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, bufnew);将 bufnew 分配给 dataset1 的形状,没有灵活性。那么最好临时创建一个 3D 新数组 bufnew0;然后在使用建议的公式创建一维数组 bufnew1 后将其删除?谢谢。
  • 是的,HD5read 似乎总是将整个数据集读入内存。在内存中重塑数组是否更好 - 这取决于您想要实现的目标以及数组的使用方式。如果尺寸是 15000*80*3,那么它是 3 600 000 的双打,大约是。 28 MB RAM(我假设双倍占用 8 个字节)。通过重塑阵列来节省 18 MB 是否至关重要,还是可以使用 28 MB?也许不值得重塑。但是如果一维数组被大量使用,那么重塑数组以使数组对缓存更加友好肯定会更好。
  • 似乎 H5Dread 不喜欢写入新的 3D 数组;当我尝试查看单个元素时出现分段错误。我使用一个非常小的数组/h5 文件进行了检查,静态数组确实有效。有什么想法吗?我遇到了这个:stackoverflow.com/questions/6393178/c-void-pointer
  • 如果在尝试查看元素时出现段错误,则可能不是 H5Dread 失败,而是访问代码失败。静态数组和“动态”数组在作为指针传递方面没有任何显着差异。我想当您查看元素或分配的内存块的大小错误时,这是​​错误的索引。错误代码是什么样子的?
  • 我在这里重写了这个问题:stackoverflow.com/questions/17110435/… 并提供了一个例子来说明这个问题。感谢您的帮助!
猜你喜欢
  • 2017-04-05
  • 1970-01-01
  • 2014-05-15
  • 2016-10-24
  • 2010-11-05
  • 1970-01-01
  • 1970-01-01
  • 2019-07-05
  • 2014-04-17
相关资源
最近更新 更多