4 维 c++ 数组的动态内存分配以创建 HDF5 数据集
Dynamic memory allocation for 4 Dimensional c++ array to create HDF5 dataset
我在 QT 中有一个程序可以创建 HDF5
数据集并将其保存在磁盘中。
起初我定义了这个数组:
int data[dataNumber][dataFilter][dataWidth][dataHeight];
其中 dataNumber=400000,dataFilter=1,dataWidth=2,dataHeight=2
并且在这个循环中我在这个数组中设置了相同的值(当然是为了简单起见):
for (int i = 0; i < dataNumber; i++)
for (int j = 0; j < dataFilter; j++)
for (int k = 0; k < dataWidth; k++)
for (int l = 0; l < dataHeight; l++)
data[i][j][k][l]=2;
之后我使用这些命令创建了 HDF5
数据集:
// Create a new file using the default property lists.
H5File file(FILE_NAME, H5F_ACC_TRUNC);
datadims[0] = dataNumber;
datadims[1] = dataFilter;
datadims[2] = dataWidth;
datadims[3] = dataHeight;
IntType datatype( PredType::NATIVE_INT );
datatype.setOrder( H5T_ORDER_LE );
DataSpace dataspace(4, datadims);
// Create the dataset.
DataSet dataset = file.createDataSet("data", datatype, dataspace);
dataset.write(data, PredType::NATIVE_INT);
一切都很好。
但是当我设置 dataWidth=4,dataHeight=4
时,segmentation fault
发生了,我认为堆栈的保留大小导致了这个问题,我应该使用 Dynamic memory allocation
.
所以我改变了 data
数组来解决这个问题:
int ****data ;
data = new int***[dataNumber];
for( int i = 0 ; i < dataNumber ; i++ )
{
data[i] = new int**[dataFilter] ;
for( int j = 0 ; j < dataFilter ; j++ )
{
data[i][j] = new int*[dataWidth] ;
for( int k = 0 ; k < dataWidth ; k++ )
data[i][j][k] = new int[ dataHeight ] ;
}
}
但是使用这个之后:
DataSet dataset = file.createDataSet("data", datatype, dataspace);
dataset.write(data, PredType::NATIVE_INT);
HDF5
数据集有很多错误的数字,例如 -1865382688 和 -1720619824 而不是真正的数字=2。
现在我不知道如何解决这个问题。希望有人能帮忙。
我建议分配一个连续的内存块,如下所示:
int *data = new int[dataNumber * dataFilter * dataWidth * dataHeight];
这意味着您将需要调用 new 运算符一次,而不是调用它数千次。这也将使清理所有这些内存变得容易,只需打一个电话:
delete []data;
而不是再次调用 delete 数千次。在那之后,你可以用这样的东西索引你的数组:
data[((i*dataFilter + j)*dataWidth + k)*dataHeight + l];
这是意料之中的:您正在传递一个指针数组(指向指向指针的指针),其中 HDF5 需要一个多维数组。 (有关内存布局差异的 ASCII 图形,请参阅我的 。)如果您希望能够将内存传递给 HDF5,则必须将内存分配到单个块中。
在 C++ 中,您需要按照 建议的方式进行操作:
int* data = new int[dataNumber*dataFilter*dataWidth*dataHeight];
然后自己做指标计算。在此不再赘述。
当然,您可以将索引计算封装在某种宏或模板中,但无论哪种方式,在 C++ 中处理 4D 数组都是一个 PITA。
但是,如果您可以选择用 C 语言编写此代码,则有更好的选择:使用真正的 4 维数组。
int (*data)[dataFilter][dataWidth][dataHeight];
data = malloc(dataNumber*sizeof(*data));
这里,data
是一个指向你的 4D 数组的 3D 巴掌的指针,你分配 dataNumber
个这样的巴掌来得到你的 4D 数组。有了这个,你可以简单地索引 4D 数组,就像你习惯的那样:
data[i][j][k][l];
C会为你做指数计算
假设您的数组大小在编译时未知,这种方法在 C++ 中是不可能的,因为 C++ 要求所有数组长度都是编译时常量。 C 没有这个限制,从 C99 开始允许动态数组大小。
例如我们要创建数组 (2,2,3,4)
像这样:
enter code hereint a[2][2][3][3]={{{{1,2,3},{4,5,6},{7,8,9}},{{10,11,12},{13,14,15},{16,17,18}}},{{{1,2,3},{4,5,6},{7,8,9}},{{10,11,12},{13,14,15},{16,17,18}}}};"
所以我们可以像
那样分配内存
enter code hereint**** data = new int***[2];for(int i = 0; i < 2; i++){
data[i] = new int**[2];
for (int j = 0; j < 3; j++){
data[i][j]=new int*[3];
for (int k=0;k<3;k++){
data[i][j][k]= new int[3];
}
}
}}
我在 QT 中有一个程序可以创建 HDF5
数据集并将其保存在磁盘中。
起初我定义了这个数组:
int data[dataNumber][dataFilter][dataWidth][dataHeight];
其中 dataNumber=400000,dataFilter=1,dataWidth=2,dataHeight=2
并且在这个循环中我在这个数组中设置了相同的值(当然是为了简单起见):
for (int i = 0; i < dataNumber; i++)
for (int j = 0; j < dataFilter; j++)
for (int k = 0; k < dataWidth; k++)
for (int l = 0; l < dataHeight; l++)
data[i][j][k][l]=2;
之后我使用这些命令创建了 HDF5
数据集:
// Create a new file using the default property lists.
H5File file(FILE_NAME, H5F_ACC_TRUNC);
datadims[0] = dataNumber;
datadims[1] = dataFilter;
datadims[2] = dataWidth;
datadims[3] = dataHeight;
IntType datatype( PredType::NATIVE_INT );
datatype.setOrder( H5T_ORDER_LE );
DataSpace dataspace(4, datadims);
// Create the dataset.
DataSet dataset = file.createDataSet("data", datatype, dataspace);
dataset.write(data, PredType::NATIVE_INT);
一切都很好。
但是当我设置 dataWidth=4,dataHeight=4
时,segmentation fault
发生了,我认为堆栈的保留大小导致了这个问题,我应该使用 Dynamic memory allocation
.
所以我改变了 data
数组来解决这个问题:
int ****data ;
data = new int***[dataNumber];
for( int i = 0 ; i < dataNumber ; i++ )
{
data[i] = new int**[dataFilter] ;
for( int j = 0 ; j < dataFilter ; j++ )
{
data[i][j] = new int*[dataWidth] ;
for( int k = 0 ; k < dataWidth ; k++ )
data[i][j][k] = new int[ dataHeight ] ;
}
}
但是使用这个之后:
DataSet dataset = file.createDataSet("data", datatype, dataspace);
dataset.write(data, PredType::NATIVE_INT);
HDF5
数据集有很多错误的数字,例如 -1865382688 和 -1720619824 而不是真正的数字=2。
现在我不知道如何解决这个问题。希望有人能帮忙。
我建议分配一个连续的内存块,如下所示:
int *data = new int[dataNumber * dataFilter * dataWidth * dataHeight];
这意味着您将需要调用 new 运算符一次,而不是调用它数千次。这也将使清理所有这些内存变得容易,只需打一个电话:
delete []data;
而不是再次调用 delete 数千次。在那之后,你可以用这样的东西索引你的数组:
data[((i*dataFilter + j)*dataWidth + k)*dataHeight + l];
这是意料之中的:您正在传递一个指针数组(指向指向指针的指针),其中 HDF5 需要一个多维数组。 (有关内存布局差异的 ASCII 图形,请参阅我的
在 C++ 中,您需要按照
int* data = new int[dataNumber*dataFilter*dataWidth*dataHeight];
然后自己做指标计算。在此不再赘述。
当然,您可以将索引计算封装在某种宏或模板中,但无论哪种方式,在 C++ 中处理 4D 数组都是一个 PITA。
但是,如果您可以选择用 C 语言编写此代码,则有更好的选择:使用真正的 4 维数组。
int (*data)[dataFilter][dataWidth][dataHeight];
data = malloc(dataNumber*sizeof(*data));
这里,data
是一个指向你的 4D 数组的 3D 巴掌的指针,你分配 dataNumber
个这样的巴掌来得到你的 4D 数组。有了这个,你可以简单地索引 4D 数组,就像你习惯的那样:
data[i][j][k][l];
C会为你做指数计算
假设您的数组大小在编译时未知,这种方法在 C++ 中是不可能的,因为 C++ 要求所有数组长度都是编译时常量。 C 没有这个限制,从 C99 开始允许动态数组大小。
例如我们要创建数组 (2,2,3,4) 像这样:
enter code hereint a[2][2][3][3]={{{{1,2,3},{4,5,6},{7,8,9}},{{10,11,12},{13,14,15},{16,17,18}}},{{{1,2,3},{4,5,6},{7,8,9}},{{10,11,12},{13,14,15},{16,17,18}}}};"
所以我们可以像
那样分配内存enter code hereint**** data = new int***[2];for(int i = 0; i < 2; i++){
data[i] = new int**[2];
for (int j = 0; j < 3; j++){
data[i][j]=new int*[3];
for (int k=0;k<3;k++){
data[i][j][k]= new int[3];
}
}
}}