Оптимизация чтения / записи огромных данных (C ++) - PullRequest
7 голосов
/ 13 марта 2009

Я хочу оптимизировать чтение / запись огромных данных для приложения моделирования C ++. Данные, обозначаемые как «карта», по существу состоят из целых, двойных чисел, чисел с плавающей точкой и одного перечисления. Большинство этих картографических данных имеют фиксированный размер, но небольшая их часть может отличаться (от нескольких до нескольких КБ) в размере. Несколько таких карт (обычно миллионы) вычисляются один раз в начале приложения и затем сохраняются в одном двоичном файле для анализа на каждом шаге моделирования.

Поскольку существует несколько миллионов карт, синтаксический анализ этого двоичного файла выполняется довольно медленно, а fseek и fread являются основными узкими местами. Я ищу альтернативный подход к тому же.

Есть указатели?

Ответы [ 8 ]

10 голосов
/ 13 марта 2009

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

Таким образом, вы не используете fseek / fread, а используете арифметику указателей. Вот пример mmap для копирования одного файла из исходного файла в файл назначения. Это может улучшить производительность.

Другие вещи, на которые вы могли бы обратить внимание, - это разбиение файлов на более мелкие файлы и использование значения хеша, соответствующего единице времени, для закрытия, а затем открытие следующего файла для продолжения моделирования, таким образом, имея дело с небольшими файлами, более агрессивно кэшируется ОС хоста!

3 голосов
/ 13 марта 2009

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

struct { 
  int x;
  enum t;
  int sz
  char variable_data[sz];
};

вы можете написать все части фиксированного размера заранее, а затем сохранить переменные части:

struct {
  int x;
  enum t;
  int sz;
  long offset_to_variable_data;
};

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

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

3 голосов
/ 13 марта 2009

Вы можете рассмотреть возможность использования файлов с отображенной памятью. Например, смотрите boost :: interprocess , поскольку они обеспечивают удобную реализацию.

Также вы можете рассмотреть возможность использования stlxxl , который обеспечивает STL-подобную функциональность для больших наборов данных на основе файлов.

И еще один - если вам нужен итератор, например, доступ к вашим данным, взгляните на boost :: iterator_facade .

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

2 голосов
/ 13 марта 2009

«миллионы» карт не похожи на большое количество данных. Что мешает вам хранить все данные в памяти?

Другим вариантом является использование некоторого стандартного формата файла, подходящего для ваших нужд, например, sqlite (используйте SQL для хранения / извлечения данных) или некоторый специализированный формат, такой как hdf5 или определение собственного форматировать что-то вроде Буферы протокола Google .

2 голосов
/ 13 марта 2009

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

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

1 голос
/ 13 марта 2009

Сохранить вычисленные данные в реляционной базе данных.

1 голос
/ 13 марта 2009

Использовать отображенный в памяти файл (http://en.wikipedia.org/wiki/Memory-mapped_file);

0 голосов
/ 07 апреля 2009

Каркасы типа Boost и ACE обеспечивают независимый от платформы доступ к отображенным в память файлам. Это должно значительно ускорить ваш анализ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...