Ответ 1
Как добавить данные в этом случае? Какую функцию я должен использовать?
Вы должны использовать гиперслои. Это то, что вам нужно написать только часть набора данных.
Функция для этого H5Sselect_hyperslab
. Используйте его на fd1
и используйте fd1
в качестве файла dataspace в своем вызове H5Dwrite
.
Я попытался поставить флаг бесконечности HDF5, но выполнение выполнения жалуется.
Вам нужно создать chunked dataset, чтобы установить максимальный размер до бесконечности. Создайте список свойств создания набора данных и используйте H5Pset_layout
, чтобы сделать его фрагментированным. Используйте H5Pset_chunk
, чтобы установить размер куска. Затем создайте свой набор данных, используя этот список свойств.
Я не хочу вычислять данные, которые я имею каждый раз; есть ли способ просто просто добавлять данные, не заботясь о значении
fdim
?
Вы можете сделать две вещи:
-
Предварительно скопируйте окончательный размер, чтобы создать набор данных достаточно большой. Это похоже на то, что вы делаете.
-
Расширьте свой набор данных при использовании
H5Dset_extent
. Для этого вам нужно установить максимальные размеры до бесконечности, чтобы вам понадобился пакетный набор данных (см. Выше).
В обоих случаях вам нужно выбрать гиперссылку в файле dataspace в вашем вызове H5Dwrite
(см. выше).
Прохождение рабочий код
#include <iostream>
#include <hdf5.h>
// Constants
const char saveFilePath[] = "test.h5";
const hsize_t ndims = 2;
const hsize_t ncols = 3;
int main()
{
Сначала создайте файл hdf5.
hid_t file = H5Fcreate(saveFilePath, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
std::cout << "- File created" << std::endl;
Затем создайте 2D-данные. Размер первого измерения неограничен. Мы первоначально устанавливаем его на 0, чтобы показать, как вы можете расширить набор данных на каждом шаге. Вы также можете установить его на размер первого буфера, который вы собираетесь писать, например. Размер второго измерения фиксирован.
hsize_t dims[ndims] = {0, ncols};
hsize_t max_dims[ndims] = {H5S_UNLIMITED, ncols};
hid_t file_space = H5Screate_simple(ndims, dims, max_dims);
std::cout << "- Dataspace created" << std::endl;
Затем создайте список свойств создания набора данных. При использовании неограниченных размеров компоновку набора данных необходимо разбить. Выбор размера блока влияет на производительность, как во времени, так и на диске. Если куски очень маленькие, у вас будет много накладных расходов. Если они слишком велики, вы можете выделить пространство, которое вам не нужно, и ваши файлы могут оказаться слишком большими. Это пример игрушки, поэтому мы выберем куски одной строки.
hid_t plist = H5Pcreate(H5P_DATASET_CREATE);
H5Pset_layout(plist, H5D_CHUNKED);
hsize_t chunk_dims[ndims] = {2, ncols};
H5Pset_chunk(plist, ndims, chunk_dims);
std::cout << "- Property list created" << std::endl;
Создайте набор данных.
hid_t dset = H5Dcreate(file, "dset1", H5T_NATIVE_FLOAT, file_space, H5P_DEFAULT, plist, H5P_DEFAULT);
std::cout << "- Dataset 'dset1' created" << std::endl;
Закрыть ресурсы. Теперь набор данных создан, поэтому нам больше не нужен список свойств. Нам больше не нужен файл dataspace, потому что, когда набор данных будет расширен, он станет недействительным, так как он все равно будет удерживать предыдущую степень. Поэтому нам все равно придется захватить обновленный файл dataspace.
H5Pclose(plist);
H5Sclose(file_space);
Теперь мы добавим два буфера в конец набора данных. Первая из них будет длиной две строки. Второй будет длиной в три строки.
Первый буфер
Мы создаем 2D-буфер (смежный по памяти, основной порядок строк).
Мы будем выделять достаточно памяти для хранения 3 строк, чтобы мы могли повторно использовать буфер.
Создадим массив указателей, чтобы мы могли использовать нотацию b[i][j]
вместо buffer[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];
}
Начальные значения в буфере, которые должны быть записаны в наборе данных:
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;
Мы создаем память, чтобы указать размер нашего буфера в памяти. Помните, что первый буфер имеет длину всего две строки.
dims[0] = 2;
dims[1] = ncols;
hid_t mem_space = H5Screate_simple(ndims, dims, NULL);
std::cout << "- Memory dataspace created" << std::endl;
Теперь нам нужно расширить набор данных. Мы устанавливаем начальный размер набора данных в 0x3, поэтому нам нужно его сначала расширить. Обратите внимание, что мы расширяем набор данных, а не его dataspace. Помните, что первый буфер имеет длину всего две строки.
dims[0] = 2;
dims[1] = ncols;
H5Dset_extent(dset, dims);
std::cout << "- Dataset extended" << std::endl;
Выберите гиперссылку в наборе данных файла.
file_space = H5Dget_space(dset);
hsize_t start[2] = {0, 0};
hsize_t count[2] = {2, ncols};
H5Sselect_hyperslab(file_space, H5S_SELECT_SET, start, NULL, count, NULL);
std::cout << "- First hyperslab selected" << std::endl;
Записать буфер в набор данных.
mem_space
и file_space
теперь должны иметь одинаковое количество элементов.
Обратите внимание, что buffer
и &b[0][0]
эквивалентны.
H5Dwrite(dset, H5T_NATIVE_FLOAT, mem_space, file_space, H5P_DEFAULT, buffer);
std::cout << "- First buffer written" << std::endl;
Теперь мы можем закрыть файл dataspace. Мы могли бы закрыть память dataspace сейчас и создать новую для второго буфера, но мы просто обновим его размер.
H5Sclose(file_space);
Второй буфер
Новые значения в буфере, добавляемые к набору данных:
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] = 3;
dims[1] = ncols;
H5Sset_extent_simple(mem_space, ndims, dims, NULL);
std::cout << "- Memory dataspace resized" << std::endl;
Расширить набор данных. Заметим, что в этом простом примере мы знаем, что 2 + 3 = 5. В общем, вы можете прочитать текущую степень из файла dataspace и добавьте к нему нужное количество строк.
dims[0] = 5;
dims[1] = ncols;
H5Dset_extent(dset, dims);
std::cout << "- Dataset extended" << std::endl;
Выберите гиперссылку в наборе данных файла. Опять же в этом простом примере мы знаем, что 0 + 2 = 2. В общем, вы можете прочитать текущую степень из файла dataspace. Второй буфер длиной три строки.
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;
}
NB: Я удалил предыдущие обновления, потому что ответ был слишком длинным. Если вам интересно, просмотрите историю.