Хранение числовых данных в двоичных файлах и структурах данных - PullRequest
0 голосов
/ 22 мая 2018

Большая тема здесь, и я новичок, я ищу какое-то направление, поскольку возможности для этой темы кажутся бесконечными.

Я выполняю численное моделирование, которое создает много данных, и я хочуотойдите от сохранения в виде обычного текста (как только я попытался сохранить все данные, созданные и получившие файл объемом 4 ТБ).

Моя симуляция включает 4 поля в течение интервала (они представлены каждый массивом)удваивается (обычно от 4000 до 16000 элементов), и они развиваются в течение примерно 1 миллиона циклов каждый раз, поэтому мы говорим о миллиардах сгенерированных двойных чисел.

Конечно, я не сохраняю все каждый раз, вместо этого я использую3 типа файлов ( эти файлы являются макетом по причинам краткости, мои настоящие файлы все записаны в формате% g, поэтому они принимают эти 7 символов + табуляции ):

  1. Файл, который сохраняет содержимое полей в определенной точке для всех временных шагов, например:

    t     Phi    Pi    Delta    A
    0     1.3    0.4   0.3      0.99
    ...
    
  2. Файл, который сохраняет всеields за весь интервал на определенном временном шаге

    x     Phi   Pi    Delta    A
    0     0.0   0.4   0.0      1.0
    ...
    
  3. Файл, который сохраняет каждые n шагов во времени и пространстве

    t    x    Phi    Pi    Delta    A
    0.0  0.0  0.0    1.3   0.0      1.0
    0.0  0.1  0.01   1.2   0.02     0.98
    ...
    0.2  0.0  0.0    1.3   0.0      1.0
    0.2  0.1  0.03   1.5   0.01     0.95
    

Затем я использую эти файлы для различных целей, таких как построение графиков, выполнение на них преобразований Фурье и их использование для возобновления симуляции.

В конечном итоге мне потребуется запустить это в кластере, поэтому я ограничен C и Iв настоящий момент не знаю, есть ли у них система баз данных / больших данных.

Мои вопросы:

  1. Каков наилучший формат для сбора этих данных, я предполагаю, что этопросто сохранив двойные в виде необработанного двоичного файла, а затем напишите программу для их последующего извлечения, но я открыт для предложений
  2. , как лучше организовать эти данные?Я смотрел вокруг и, возможно, я мог бы написать дерево, в котором листья являются массивами
  3. А как насчет сжатия?

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Каков наилучший формат для хранения этих данных

Это зависит от точности и структуры значений.

Если 7 значащих десятичных знаков точностидостаточно, и значения соответствуют 2 -126 до 2 127 (1,17549 × 10 -38 до 1,70141 × 10 38 ),тогда вы можете использовать формат IEEE-754 binary32 .На всех машинах и кластерах, используемых для высокопроизводительных вычислений, тип float соответствует этому.

Если вам нужно 15 значащих десятичных разрядов точности и / или диапазон от 2 -1023 до 2 1023 (1.11254 × 10 -308 до 8.98847 × 10 308 ), используйте формат IEEE-754 binary64 .Опять же, на всех машинах и кластерах, используемых для высокопроизводительных вычислений, тип double соответствует этому.

Остается проблема с порядком байтов и идентификацией полей.

Предполагается, что вы не хотитеЧтобы использовать любые ресурсы HPC для преобразования данных во время вычислений, лучше всего хранить данные в собственном порядке байтов, но включать заголовок в файл, который содержит известное значение «прототипа» для каждого типа значения, чтобы читатель мог проверить ихпроверить, нужна ли компенсация порядка байтов для правильной интерпретации полей;плюс дескрипторы для каждого из полей.

(Например, я реализовал это таким образом, чтобы можно было легко читать файлы на C и нативном Fortran 95 с минимальными расширениями компилятора, также позволяя каждому вычислениюузел для сохранения результатов в локальном файле, при этом читатели автоматически получают данные из нескольких файлов параллельно. Обычно я поддерживаю только u8, s8, u16, s16, u32, s32,u64, s64 (для целых чисел без знака и со знаком различных битов) и r32 и r64 для вещественных чисел одинарной и двойной точности или Binary32 и Binary64 соответственно).Мне пока не нужны форматы комплексных чисел.)

Большинство людей предпочитают использовать для этого, например, NetCDF , но мой подход отличается тем, что авторы создают данные в собственном формате, а не в нормализованномформат;я намереваюсь минимизировать накладные расходы во время создания / моделирования данных и перекладывать все накладные расходы на читателей.

Если вы считаете, что небольшие накладные расходы во время генерации файла (во время симуляции) приемлемы, и у вас нет опытапри написании подпрограмм в двоичном формате я рекомендую использовать NetCDF.

Обратите внимание, что если операторы кластера HPC обнаружат, что ваши ресурсы моделирования / вычислений тратят впустую (например, средняя загрузка ядра низкая или она не масштабируется)для нескольких ядер) вам может быть запрещено запускать симуляцию в кластере.Очевидно, это зависит от местной политики и политики.

Каков наилучший способ организации этих данных?

Из-за очень большого объема данных параллельные файлы может быть вашим лучшим вариантом.(Некоторые кластеры имеют быстрое локальное хранилище, и в этом случае хранение данных непосредственно с каждого узла в локальный файл и сбор этих локальных файлов в кучу после запуска может быть предпочтительнее. Если это меняется, обратитесь к администратору кластера.)

Другими словами, один файл на один связанный массив данных.

Нетрудно написать библиотеку, которая может читать из нескольких файлов параллельно, но правильно анализировать и управлять структурированными файлами намного сложнее.

Кроме того, разбиение данных на отдельные файлы часто упрощает передачу данных.Если у вас есть файл данных размером 16 ТиБ, вы в основном ограничены сетевым транспортом и даже можете ограничиться тем, какие файловые системы вы можете использовать.Однако, если у вас есть, скажем, 128 файлов, каждый из которых имеет размер около 128 ГиБ, у вас будет гораздо больше опций, и вы, вероятно, сможете хранить некоторые из них в автономном хранилище, работая над другими.В частности, многие операторы кластера HPC позволяют напрямую передавать файлы на локальные носители (диски USB3 или карты памяти), чтобы уменьшить перегрузку при передаче по сети.

Как насчет сжатия?

Вы можете сжимать данные, если это необходимо, но я лично сделал бы это в момент, когда данные собираются / объединяются / обрабатываются на вашей собственной рабочей станции, а не в точкегде это генерируется.Вычисления HPC стоят дорого;гораздо дешевле обрабатывать данные при первой обработке.

Двоичные данные сжимаются не так хорошо, как текст, но текстовые файлы гораздо большего размера при том же разрешении данных.Это означает, что важно в любом случае выбрать правильный тип значения, используемый для хранения каждого параметра.И вы хотите сохранить этот тип во всем наборе, а не переходить от записи к другому, чтобы обеспечить простоту обработки.

Что касается алгоритмов сжатия / распаковки, я бы выбрал zlib и xz .См., Например, здесь для быстрого просмотра кривых скорости / степени сжатия.Проще говоря, zlib работает быстро, но обеспечивает умеренные коэффициенты сжатия, тогда как xz медленнее, но обеспечивает гораздо лучшие коэффициенты сжатия.

0 голосов
/ 22 мая 2018

Предполагая, что значения находятся в диапазоне от 0,00 до 9,99, вы можете использовать 4-битное кодирование, включая разделитель чисел и индикатор конца строки:

/*
 0    1    2    3    4    5    6    7    8    9    \t   \n
 0000 0001 0010 0100 0100 0101 0110 0111 1000 1001 1010 1011

 1.99\t --> 0001 1001 1001 1010
*/

uint16_t cvtnum(double d, int endl)
{
    char snum[6], *cp=snum;
    uint16_t out= 0;
    sprintf(snum,"%.2f",d);
    while (*cp) {
        if (*cp!='.') out = (out<<4) | (*cp - '0');
        cp++;
    }
    if (endl)
        out = (out<<4) | (11);
    else
        out = (out<<4) | (10);
    return out;
}

Обратите внимание, что десятичная точка не закодированаи предполагается после первой цифры.Если endl равно true, добавляется индикатор конца строки, в противном случае - разделитель чисел.

...