Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 写作及;将浮点数组附加到C+中hdf5文件中的唯一数据集+;_C++_Arrays_File_Append_Hdf5 - Fatal编程技术网

C++ 写作及;将浮点数组附加到C+中hdf5文件中的唯一数据集+;

C++ 写作及;将浮点数组附加到C+中hdf5文件中的唯一数据集+;,c++,arrays,file,append,hdf5,C++,Arrays,File,Append,Hdf5,我正在处理大量文件,每次处理文件都会输出数千个浮点数组,我将将所有文件的数据存储在一个巨大的数据集中,存储在一个hdf5中,以供进一步处理 现在的问题是,我对如何将数据附加到hdf5文件感到困惑。(上面代码中的注释)在上面的2个循环中,正如您所看到的,我希望一次将一维浮点数组附加到hdf5中,而不是作为一个整体。我的数据以TB为单位,我们只能将数据附加到文件中 有几个问题: 在这种情况下,如何附加数据?我必须使用什么样的函数 现在,我有fdim[0]=928347543,我试着把HDF5的无穷大

我正在处理大量文件,每次处理文件都会输出数千个浮点数组,我将将所有文件的数据存储在一个巨大的数据集中,存储在一个hdf5中,以供进一步处理

现在的问题是,我对如何将数据附加到hdf5文件感到困惑。(上面代码中的注释)在上面的2个循环中,正如您所看到的,我希望一次将一维浮点数组附加到hdf5中,而不是作为一个整体。我的数据以TB为单位,我们只能将数据附加到文件中

有几个问题:

  • 在这种情况下,如何附加数据?我必须使用什么样的函数
  • 现在,我有fdim[0]=928347543,我试着把HDF5的无穷大标志放进去,但是运行时执行会抱怨。有办法做到这一点吗?我不想每次都计算我拥有的数据;有没有一种方法可以简单地继续添加数据,而不考虑fdim的价值
  • 或者这是不可能的

    编辑:

    我一直在遵循Simon的建议,现在这里是我的更新代码:

    hid_t desFi5;
    hid_t fid1;
    hid_t propList;
    hsize_t fdim[2];
    
    desFi5 = H5Fcreate(saveFilePath, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
    
    fdim[0] = 3;
    fdim[1] = 1;//H5S_UNLIMITED;
    
    fid1 = H5Screate_simple(2, fdim, NULL);
    
    cout << "----------------------------------Space done\n";
    
    propList = H5Pcreate( H5P_DATASET_CREATE);
    
    H5Pset_layout( propList, H5D_CHUNKED );
    
    int ndims = 2;
    hsize_t chunk_dims[2];
    chunk_dims[0] = 3;
    chunk_dims[1] = 1;
    
    H5Pset_chunk( propList, ndims, chunk_dims );
    
    cout << "----------------------------------Property done\n";
    
    hid_t dataset1 = H5Dcreate( desFi5, "des", H5T_NATIVE_FLOAT, fid1, H5P_DEFAULT, propList, H5P_DEFAULT);
    
    cout << "----------------------------------Dataset done\n";
    
    bufi = new float*[1];
    bufi[0] = new float[3];
    bufi[0][0] = 0;
    bufi[0][1] = 1;
    bufi[0][2] = 2;
    
    //hyperslab
    hsize_t start[2] = {0,0};
    hsize_t stride[2] = {1,1};
    hsize_t count[2] = {1,1};
    hsize_t block[2] = {1,3};
    
    H5Sselect_hyperslab( fid1, H5S_SELECT_OR, start, stride, count, block);     
    cout << "----------------------------------hyperslab done\n";   
    
    H5Dwrite(dataset1, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, *bufi);
    
    fdim[0] = 3;
    fdim[1] = H5S_UNLIMITED;    // COMPLAINS HERE
    H5Dset_extent( dataset1, fdim );
    
    cout << "----------------------------------extent done\n";
    
    //hyperslab2
    hsize_t start2[2] = {1,0};
    hsize_t stride2[2] = {1,1};
    hsize_t count2[2] = {1,1};
    hsize_t block2[2] = {1,3};
    
    H5Sselect_hyperslab( fid1, H5S_SELECT_OR, start2, stride2, count2, block2);     
    cout << "----------------------------------hyperslab2 done\n";  
    
    H5Dwrite(dataset1, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, *bufi);
    
    cout << "----------------------------------H5Dwrite done\n";        
    H5Dclose(dataset1);
    cout << "----------------------------------dataset closed\n";   
    H5Pclose( propList );   
    cout << "----------------------------------property list closed\n"; 
    H5Sclose(fid1); 
    cout << "----------------------------------dataspace fid1 closed\n";    
    H5Fclose(desFi5);       
    cout << "----------------------------------desFi5 closed\n";    
    
    目前,我发现使用H5Dset_区段将内容设置为unlimited在运行时仍然会导致问题。(在上面的代码中,有问题的函数标记为
    //这里投诉
    )。我已经得到了Simon指定的块数据,那么这里有什么问题

    另一方面,如果没有H5Dset_区段,我可以编写一个[0,1,2]的测试数组,但是我们如何使输出上面的代码像这样将测试数组写入文件:

    [0, 1, 2]
    [0, 1, 2]
    [0, 1, 2]
    [0, 1, 2]
    ...
    ...
    
    回想一下:这只是一个测试数组,实际数据更大,我无法将整个数据保存在RAM中,因此我必须一次一部分地将数据放入其中

    编辑2:

    我更多地采纳了西蒙的建议。以下是关键部分:

    hsize_t n = 3, p = 1;
    float *bufi_data = new float[n * p];
    float ** bufi = new float*[n];
    for (hsize_t i = 0; i < n; ++i){
        bufi[i] = &bufi_data[i * n];
    }
    
    bufi[0][0] = 0.1;
    bufi[0][1] = 0.2;
    bufi[0][2] = 0.3;
    
    //hyperslab
    hsize_t start[2] = {0,0};
    hsize_t count[2] = {3,1};
    
    H5Sselect_hyperslab( fid1, H5S_SELECT_SET, start, NULL, count, NULL);
    cout << "----------------------------------hyperslab done\n";   
    
    H5Dwrite(dataset1, H5T_NATIVE_FLOAT, H5S_ALL, fid1, H5P_DEFAULT, *bufi);
    
    bufi[0][0] = 0.4;
    bufi[0][1] = 0.5;
    bufi[0][2] = 0.6;
    
    hsize_t fdimNew[2];
    fdimNew[0] = 3;
    fdimNew[1] = 2;
    H5Dset_extent( dataset1, fdimNew );
    
    cout << "----------------------------------extent done\n";
    
    //hyperslab2
    hsize_t start2[2] = {0,0}; //PROBLEM
    hsize_t count2[2] = {3,1};
    
    H5Sselect_hyperslab( fid1, H5S_SELECT_SET, start2, NULL, count2, NULL);     
    cout << "----------------------------------hyperslab2 done\n";  
    
    H5Dwrite(dataset1, H5T_NATIVE_FLOAT, H5S_ALL, fid1, H5P_DEFAULT, *bufi);
    
    在进一步试验了
    start2
    count2
    之后,我发现这些变量只影响
    bufi
    的起始索引和递增索引。它根本不会移动我的数据集的写入索引的位置

    回顾:最终结果必须是:

    0.1 0.2 0.3
    0.4 0.5 0.6
    
    另外,西蒙,
    H5Dwrite
    必须是
    bufi
    而不是
    *bufi
    ,因为
    bufi
    给我的是完全随机的数字

    更新3:

    对于Simon建议的选择部分:

    hsize_t start[2] = {0, 0};
    hsize_t count[2] = {1, 3};
    
    hsize_t start[2] = {1, 0};
    hsize_t count[2] = {1, 3};
    
    这些将给出以下错误:

    HDF5-DIAG: Error detected in HDF5 (1.8.10) thread 0:
      #000: /home/hdftest/snapshots-bin-hdf5_1_8_10/current/src/H5Dio.c line 245 in H5Dwrite(): file selection+offset not within extent
        major: Dataspace
        minor: Out of range
    
    count[2]
    应该是
    {3,1}
    ,而不是
    {1,3}
    ,我想是吧?对于
    start[2]
    ,如果我没有将它设置为
    {0,0}
    ,它将总是大声说出上面的错误

    你确定这是正确的吗

    在这种情况下,如何附加数据?我必须使用什么样的函数

    您必须使用超实验室。这就是只需编写数据集的一部分所需的内容。 这样做的功能是。在
    fd1
    上使用它,并在
    H5Dwrite
    调用中使用
    fd1
    作为文件数据空间

    我曾尝试将HDF5的infinity标志放入,但运行时执行出现问题

    您需要创建一个分块数据集,以便能够将其最大大小设置为无穷大。创建数据集创建属性列表,并使用将其分块。用于设置块大小。然后使用此属性列表创建数据集

    我不想每次都计算我拥有的数据;有没有一种方法可以简单地继续添加数据,而不关心
    fdim
    的值

    你可以做两件事:

  • 预计算最终大小,以便创建足够大的数据集。看起来你就是这么做的

  • 使用扩展数据集。为此,需要将最大维度设置为无穷大,因此需要一个分块数据集(见上文)

  • 在这两种情况下,您都需要在
    H5Dwrite
    调用中选择文件数据空间上的hyperslab(请参见上文)

    演练 现在,我们将在数据集的末尾附加两个缓冲区。 第一条有两行。 第二条是三行

        dims[0] = 2;
        dims[1] = ncols;
        hid_t mem_space = H5Screate_simple(ndims, dims, NULL);
        std::cout << "- Memory dataspace created" << std::endl;
    
        dims[0] = 2;
        dims[1] = ncols;
        H5Dset_extent(dset, dims);
        std::cout << "- Dataset extended" << std::endl;
    
        dims[0] = 3;
        dims[1] = ncols;
        H5Sset_extent_simple(mem_space, ndims, dims, NULL);
        std::cout << "- Memory dataspace resized" << std::endl;
    
        file_space = H5Dget_space(dset);
        start[0] = 2;
        start[1] = 0;
        count[0] = 3;
        count[1] = ncols;
        H5Sselect_hyperslab(file_space, H5S_SELECT_SET, start, NULL, count, NULL);
        std::cout << "- Second hyperslab selected" << std::endl;
    
    第一缓冲区 我们创建一个2D缓冲区(内存中连续,行主顺序)。 我们将分配足够的内存来存储3行,这样我们就可以重用缓冲区。 让我们创建一个指针数组,以便使用
    b[i][j]
    符号 而不是
    缓冲区[i*ncols+j]
    。这纯粹是美学上的

        hsize_t nlines = 3;
        float *buffer = new float[nlines * ncols];
        float **b = new float*[nlines];
        for (hsize_t i = 0; i < nlines; ++i){
            b[i] = &buffer[i * ncols];
        }
    
    我们创建一个内存数据空间来指示内存中缓冲区的大小。 请记住,第一个缓冲区只有两行长

        dims[0] = 2;
        dims[1] = ncols;
        hid_t mem_space = H5Screate_simple(ndims, dims, NULL);
        std::cout << "- Memory dataspace created" << std::endl;
    
        dims[0] = 2;
        dims[1] = ncols;
        H5Dset_extent(dset, dims);
        std::cout << "- Dataset extended" << std::endl;
    
        dims[0] = 3;
        dims[1] = ncols;
        H5Sset_extent_simple(mem_space, ndims, dims, NULL);
        std::cout << "- Memory dataspace resized" << std::endl;
    
        file_space = H5Dget_space(dset);
        start[0] = 2;
        start[1] = 0;
        count[0] = 3;
        count[1] = ncols;
        H5Sselect_hyperslab(file_space, H5S_SELECT_SET, start, NULL, count, NULL);
        std::cout << "- Second hyperslab selected" << std::endl;
    
    我们现在可以关闭文件数据空间。 我们现在可以关闭内存数据空间,为第二个缓冲区创建一个新的数据空间, 但我们只会更新它的大小

        H5Sclose(file_space);
    
    第二缓冲区 缓冲区中要附加到数据集的新值:

        b[0][0] = 0.1;
        b[0][1] = 0.2;
        b[0][2] = 0.3;
        b[1][0] = 0.4;
        b[1][1] = 0.5;
        b[1][2] = 0.6;
    
        b[0][0] = 1.1;
        b[0][1] = 1.2;
        b[0][2] = 1.3;
        b[1][0] = 1.4;
        b[1][1] = 1.5;
        b[1][2] = 1.6;
        b[2][0] = 1.7;
        b[2][1] = 1.8;
        b[2][2] = 1.9;
    
    调整内存数据空间的大小以指示缓冲区的新大小。 第二个缓冲区有三行长

        dims[0] = 2;
        dims[1] = ncols;
        hid_t mem_space = H5Screate_simple(ndims, dims, NULL);
        std::cout << "- Memory dataspace created" << std::endl;
    
        dims[0] = 2;
        dims[1] = ncols;
        H5Dset_extent(dset, dims);
        std::cout << "- Dataset extended" << std::endl;
    
        dims[0] = 3;
        dims[1] = ncols;
        H5Sset_extent_simple(mem_space, ndims, dims, NULL);
        std::cout << "- Memory dataspace resized" << std::endl;
    
        file_space = H5Dget_space(dset);
        start[0] = 2;
        start[1] = 0;
        count[0] = 3;
        count[1] = ncols;
        H5Sselect_hyperslab(file_space, H5S_SELECT_SET, start, NULL, count, NULL);
        std::cout << "- Second hyperslab selected" << std::endl;
    
    dims[0]=3;
    dims[1]=ncols;
    H5Sset_extent_simple(内存空间、NDIM、dims、NULL);
    
    std::我可以按照你的建议更新上面问题中的代码吗?我已经更新了我的问题,也按照你的更新。好的@Karl,这次我自己尝试了,我发布了一个工作代码的要点。谢谢你,Simon。在我看到了整件事之后,我现在看到了所有我误解的地方。我的天啊…正是这些答案让我想开一个虚拟账户,这样我可以投票两次。。。
        dims[0] = 3;
        dims[1] = ncols;
        H5Sset_extent_simple(mem_space, ndims, dims, NULL);
        std::cout << "- Memory dataspace resized" << std::endl;
    
        dims[0] = 5;
        dims[1] = ncols;
        H5Dset_extent(dset, dims);
        std::cout << "- Dataset extended" << std::endl;
    
        file_space = H5Dget_space(dset);
        start[0] = 2;
        start[1] = 0;
        count[0] = 3;
        count[1] = ncols;
        H5Sselect_hyperslab(file_space, H5S_SELECT_SET, start, NULL, count, NULL);
        std::cout << "- Second hyperslab selected" << std::endl;
    
        H5Dwrite(dset, H5T_NATIVE_FLOAT, mem_space, file_space, H5P_DEFAULT, buffer);
        std::cout << "- Second buffer written" << std::endl;
    
        delete[] b;
        delete[] buffer;
        H5Sclose(file_space);
        H5Sclose(mem_space);
        H5Dclose(dset);
        H5Fclose(file);
        std::cout << "- Resources released" << std::endl;
    }