В настоящее время я пишу программу, которая сможет обрабатывать основные данные.
Поэтому я обрабатываю файлы размером от 1 МБ до 50 ГБ (и, возможно, в будущем будет больше).
Я прочитал несколько учебных пособий, касающихся файлов с отображенной памятью, и теперь использую файлы с отображенной памятью для управления вводом-выводом данных, то есть чтения и записи данных с / на жесткий диск.
Теперь я также обрабатываю данные, и мне нужны временные массивы того же размера, что и данные. Мой вопрос сейчас заключается в том, стоит ли мне использовать для этого файлы, отображаемые в память, или мне нужно каким-то образом управлять им в операционной системе без явного определения файлов, отображаемых в память.
Проблема заключается в следующем:
Я работаю на нескольких платформах, но всегда с 64-битными системами. Теоретически, 64-битное виртуальное адресное пространство определенно достаточно для моих нужд. Однако в Windows максимальное виртуальное адресное пространство, по-видимому, ограничено операционной системой, то есть пользователь может установить, разрешен ли пейджинг, и какой максимальный размер виртуальной памяти разрешен. Также я где-то читал, что максимальная виртуальная память в Windows 64 не 2 ^ 64, а где-то на 2 ^ 40 или что-то подобное, что для меня все еще было бы достаточно, но кажется довольно странным ограничением.
Кроме того, Windows имеет некоторые странные ограничения, такие как массивы с максимальным размером 2 ^ 31 элементов, независимо от типа массива. Я не знаю, как все это обрабатывается на Linux, но я думаю, что это рассматривается аналогично. Вероятно, максимально допустимая виртуальная память = OS-RAM + размер раздела подкачки? Таким образом, есть много вещей, с которыми нужно бороться, если я хочу использовать систему для обработки моих данных, превышающих размер оперативной памяти.
Я даже не знаю, смогу ли я как-то использовать в C ++ все 64-битное виртуальное адресное пространство. В моем коротком тесте я получил ошибку компилятора, когда не удалось инициализировать более 2 ^ 31 элементов, но я думаю, что легко выйти за пределы этого, используя std :: vector и тому подобное.
Однако, с другой стороны, при использовании отображенного в память файла это всегда будут данные, записанные на жесткий диск со всеми операциями записи в память. Специально для данных, которые меньше моей физической памяти, это должно быть довольно большим узким местом. Или он избегает записи до тех пор, пока не должен из-за превышения оперативной памяти ???
Преимущества отображаемых в память файлов заключаются в межпроцессном обмене данными с общей памятью или во временном обмене данными, так что я запускаю приложение, что-то пишу, покидаю приложение, а затем перезапускаю его и эффективно считываю только те данные в оперативную память, которые мне нужны.
Поскольку мне нужно обрабатывать все данные и только в одном экземпляре выполнения одним процессом, в моем случае оба преимущества не проявляются.
Примечание. Потоковый подход как альтернативное решение моей проблемы на самом деле неосуществим, поскольку я сильно зависим от произвольного доступа к данным.
В идеале мне хотелось бы, чтобы я мог обрабатывать все модели независимо от их размера и ограничений набора рабочих пределов, но обрабатывать все, что возможно в ОЗУ, и только при превышении физического предела использовать файлы, отображенные в памяти, или другие механизмы ( если есть какие-либо другие) для подкачки ОЗУ, превышающей данные, в идеале управляется операционной системой.
В заключение, каков наилучший подход для обработки этих временных существующих данных? Если я могу сделать это без файлов с отображенной памятью и независимо от платформы, вы можете дать мне какой-нибудь фрагмент кода или что-то вроде этого и объяснить, как это работает, чтобы избежать этих ограничений ОС?
Может быть, немного поздно, но это интересный вопрос.
Однако, с другой стороны, при использовании отображенного в память файла это всегда будут данные, записанные на жесткий диск со всеми операциями записи в память. Специально для данных, которые меньше моей физической памяти, это должно быть довольно большим узким местом. Или он избегает записи до тех пор, пока не должен из-за превышения оперативной памяти ???
Чтобы избежать записи на диск при достаточном объеме памяти, вы должны открыть файл как «временный» (FILE_ATTRIBUTE_TEMPORARY
) с FILE_FLAG_DELETE_ON_CLOSE
, Это намекает ОС на задержку записи на диск как можно дольше.
Что касается ограничений по размеру массива: вероятно, лучше предоставить свои собственные структуры данных и доступ к отображенным представлениям. Для больших наборов данных вы можете использовать несколько различных (меньших) отображенных видов, которые вы можете отображать и удалять при необходимости.
Поскольку никто не ответил, я обновлю статус вопроса самостоятельно.
После того, как я, к счастью, сегодня связался с библиотекой boost interprocess, я обнаружил managed_mapped_file, который даже позволяет мне выделять векторы в отображенном диапазоне, что делает их почти такими же простыми в использовании, как и программирование без отображения файлов вообще.
Кроме того, я обнаружил, что:
Если несколько процессов отображают один и тот же файл, и процесс изменяет
диапазон памяти из отображаемой области, которая также отображается другими
процесс, изменения изначально видны другим процессам.
Однако содержимое файла на диске не обновляется сразу, так как
это ухудшит производительность (запись на диск в несколько раз медленнее
чем запись в память). Если пользователь хочет убедиться, что файл
содержимое было обновлено, оно может сбрасывать диапазон от представления к
диск.
http://www.boost.org/doc/libs/1_54_0/doc/html/interprocess/sharedmemorybetweenprocesses.html
Так что, надеюсь, он начинает писать только когда я превышаю физическую память системы.
Я еще не делал никаких измерений скорости и, вероятно, не буду делать некоторые из них.
Теперь я могу жить с этим решением довольно хорошо.
Однако я оставлю этот вопрос без ответа и открытым.
В какой-то момент кто-то может найти вопрос и может дать дополнительные советы, такие как, как предотвратить сброс данных до того момента, когда это действительно необходимо, или у него есть другие идеи / советы, как обрабатывать неосновные данные.