Я занимаюсь симуляцией физики, и, поскольку я довольно новичок в программировании, я продолжаю сталкиваться с проблемами при создании больших программ (в основном с памятью). Я знаю о динамическом распределении и удалении памяти (new / delete и т. Д.), Но мне нужен лучший подход к структурированию программы.
Допустим, я моделирую эксперимент, который длится несколько дней с очень большой частотой дискретизации. Мне нужно смоделировать миллиард образцов и выполнить их.
Как упрощенная версия, мы скажем, что программа берет напряжения V [i] и суммирует их в пять:
т.е. NewV [0] = V [0] + V [1] + V [2] + V [3] + V [4]
тогда NewV [1] = V [1] + V [2] + V [3] + V [4] + V [5]
затем NewV [2] = V [2] + V [3] + V [4] + V [5] + V [6] ... и это продолжается для миллиарда выборок.
В конце концов, у меня будет V [0], V [1], ..., V [1000000000], тогда как вместо этого единственные, которые мне нужно сохранить для следующего шага, это последние 5 V [i] s.
Как бы я удалил / освободил часть массива, чтобы память снова могла свободно использоваться (скажем, V [0] после первой части примера, где она больше не нужна)? Есть ли альтернативы тому, как структурировать такую программу?
Я слышал о malloc / free, но слышал, что они не должны использоваться в C ++ и что есть лучшие альтернативы.
Огромное спасибо!
tldr; что делать с частями массивов (отдельными элементами), которые мне больше не нужны, которые занимают огромное количество памяти?
V
новом массиве. В целом, однако, я думаю, что ваша проблема заключается либо в ваших алгоритмах, либо в ваших структурах данных, и, поскольку у нас нет никаких деталей, трудно понять, как это сделать эффективно.Ответы:
То, что вы описываете, «сглаживание на пять», представляет собой цифровой фильтр с конечной импульсной характеристикой (FIR). Такие фильтры реализованы с помощью кольцевых буферов. Вы сохраняете только последние N значений, сохраняете индекс в буфере, который сообщает вам, где находится самое старое значение, вы перезаписываете текущее самое старое значение самым новым на каждом шаге и каждый раз шагаете по индексу по кругу.
Вы храните свои собранные данные, которые собираетесь сжать, на диске.
В зависимости от вашей среды, это может быть одним из тех мест, где вам лучше получить опытную помощь. В университете вы помещаете заметку на доске объявлений в Департаменте компьютерных наук, предлагая заработную плату студентов (или даже ставки студенческого консалтинга) за несколько часов работы, чтобы помочь вам сжать ваши данные. Или, может быть, вы предлагаете очки возможностей для студентов бакалавриата. Или что-то.
источник
Любая проблема может быть решена путем добавления дополнительного уровня косвенности. Так сделай это.
Вы не можете удалить часть массива в C ++. Но вы можете создать новый массив, содержащий только те данные, которые вы хотите сохранить, а затем удалить старый. Таким образом, вы можете создать структуру данных, которая позволит вам «удалять» ненужные элементы спереди. Что он на самом деле сделает, так это создаст новый массив и скопирует невосстановленные элементы в новый, затем удалит старый.
Или вы можете просто использовать
std::deque
, который может эффективно сделать это уже.deque
или «двусторонняя очередь» - это структура данных, предназначенная для случаев, когда вы удаляете элементы с одного конца, добавляя элементы с другого.источник
std::deque
есть путьdeque
. То есть хранение и повторное использование выделенных ресурсов по запросу. Так чтоdeque
кажется вполне адекватным решением проблемы.Ответы FIR и SMA, которые вы получили, хороши в вашем случае, однако я хотел бы воспользоваться возможностью для продвижения более общего подхода.
Здесь у вас есть поток данных: вместо того, чтобы структурировать вашу программу в 3 больших шага (получение данных, вычисление, вывод результата), которые требуют загрузки всех данных в память одновременно, вы можете вместо этого структурировать ее как конвейер .
Конвейер начинается с потока, преобразует его и переносит в сток.
В вашем случае конвейер выглядит так:
C ++ имеет тенденцию использовать итераторы, а не потоки, но, честно говоря, потоки легче моделировать (есть предложение для диапазонов, которые были бы похожи на потоки):
И тогда, трубопровод выглядит так:
Потоки не всегда применимы (они не работают, когда вам нужен произвольный доступ к данным), но когда они есть, они качаются: работая с очень небольшим объемом памяти, вы сохраняете все это в кеше ЦП.
С другой стороны: кажется, что ваша проблема может быть «смущающей параллелью», вы можете разбить ваш большой файл на куски (имейте в виду, что для обработки по окнам из 5 вам нужно иметь 4 общих элемента на каждой границе) а затем обрабатывать куски параллельно.
Если узким местом является ЦП (а не ввод-вывод), вы можете ускорить его, запустив один процесс на ядро после разделения файлов в примерно равных количествах.
источник