#arrays #c #file #append #hdf5
#массивы #c #файл #добавить #hdf5
Вопрос:
Мне нужно создать файлы HDF5 из изображений, которые поставляются с меткой времени в C. Я НЕ знаю заранее, сколько из этих пар я получу, поэтому набор данных фиксированного размера — это не вариант.
Образец моих данных представлен в виде большого (~ 12 x 10 ^ 6) массива uint8_t, содержащего уменьшенную версию изображения в дополнение к метке времени uint64_t. Я добавил эквиваленты своих решений на языке Си для лучшего понимания.
Я мог бы придумать 2 возможных решения для этого, но у меня есть свои проблемы с обоими. Я был бы признателен за некоторые указания здесь:
ВЕРСИЯ 1
Я создаю 2-D набор данных uint8_t с начальным размером 0. На ходу я расширяю набор данных во время каждой итерации и записываю данные изображения в файл HDF5. Здесь я планировал поместить временные метки в соответствующий массив uint64_t в атрибутах dataset. Проблема в том, что я не нашел способа расширить массив атрибутов на ходу, поэтому мне пришлось бы сохранить все временные метки во временном массиве и добавить его к атрибутам позже. Это не только отнимает много памяти, но и в случае сбоя у меня остаются изображения, но без временных меток.
uint8_t images[][IMG_BUF_SIZE];
(as attribute:)
uint64_t timestamps[];
ВЕРСИЯ 2
Я попытался использовать составные типы данных, чтобы у меня был одномерный массив выборок составного типа. Каждый образец будет содержать временную метку uint64_t и большой массив uint8_t. Проблема, с которой я сталкиваюсь, заключается в том, что я прочитал в документах HDF5, что в составных типах данных не рекомендуется иметь «большие массивы».
typedef struct
{
uint64_t timestamp;
uint8_t payload[IMG_BUF_SIZE];
} time_image_t;
time_image_t array[];
Как это можно сделать? Наборы данных этих типов должны быть довольно распространенными, но я не смог найти стандартный способ сделать это.
Спасибо!
Комментарии:
1. Я советую прочитать раздел «Особые вопросы» в главе «Атрибуты» Руководства пользователя HDF5 . В нем говорится: «Мы считаем, что максимальный размер атрибута составляет 64 тысячи байт» . Итак, если ваш массив временной карты составляет <64 КБ, все будет в порядке. Если нет, есть два способа сохранить атрибуты> 64 Тыс. байт: 1) в плотном хранилище атрибутов или 2) в отдельном наборе данных. В Руководстве пользователя приведены примеры обоих методов. См. pgs 306-308 в Руководстве для выпуска 1.10.
Ответ №1:
Лучший способ решить эту проблему — использовать составной набор данных HDF5 (содержащий два элемента: timestamp
и payload
), как описано в версии 2 выше.
Кроме того, набор данных должен быть расширяемым, чтобы он мог увеличиваться в соответствии с размером данных, которые вы получите (что заранее неизвестно). Чтобы избежать перезаписи уже сохраненных данных в наборе данных, вам нужно будет работать с выделениями (гиперслав или точка) при записи в него данных.
Одним из способов решения вашего варианта использования может быть использование HDFql на C следующим образом (обратите внимание, что в этом примере я просто добавляю две «строки» в набор данных — у вас может быть цикл, добавляющий столько «строк», сколько необходимо для решения того, что вы имеете в виду):
#include <stdio.h>
#include <stddef.h>
#include "HDFql.h"
#define IMG_BUF_SIZE 3
typedef struct
{
uint64_t timestamp;
uint8_t payload[IMG_BUF_SIZE];
}time_image_t;
int main(int argc, char *argv[])
{
// declare variables
char script[1024];
time_image_t data;
// create HDF5 file named 'data.h5' and use (i.e. open) it
hdfql_execute("create and use file data.h5");
// prepare script to create an extendable dataset named 'dset' of data type compound (containing two members named 'timestamp' and 'payload')
sprintf(script, "create dataset dset as compound(timestamp as unsigned bigint offset %d, payload as unsigned tinyint(%d) offset %d)(unlimited) size %d", offsetof(time_image_t, timestamp), IMG_BUF_SIZE, offsetof(time_image_t, payload), sizeof(time_image_t));
// execute script
hdfql_execute(script);
// register variable 'data' for subsequent usage (by HDFql)
hdfql_variable_register(amp;data);
// populate variable 'data' with some values
data.timestamp = 123;
data.payload[0] = 10;
data.payload[1] = 20;
data.payload[2] = 30;
// insert data into last row of dataset 'dset' thanks to a point selection
hdfql_execute("insert into dset(-1) values from memory 0");
// populate variable 'data' with more values
data.timestamp = 456;
data.payload[0] = 75;
data.payload[1] = 85;
data.payload[2] = 95;
// alter (i.e. change) dimension of dataset 'dset' to 1
hdfql_execute("alter dimension dset to 1");
// insert data into last row of dataset 'dset' thanks to a point selection
hdfql_execute("insert into dset(-1) values from memory 0");
// unregister variable 'data' as it is no longer used (by HDFql)
hdfql_variable_unregister(amp;data);
// close HDF5 file 'data.h5'
hdfql_execute("close file");
return 0;
}