Отказ от ответственности: я прошу прощения за многословность этого вопроса (хотя я думаю, что это интересная проблема!), Но я не могу придумать, как его более кратко сформулировать.
Я провел много часов в поисках бесчисленных способов решения проблемы доступа к файлам с несколькими ГБ в 32-битном процессе на 64-битной Windows 7, начиная от /LARGEADDRESSAWARE
в VirtualAllocEx
ТРЕПЕТ. Мне несколько удобно писать систему отображения с несколькими представлениями в Windows (CreateFileMapping, MapViewOfFile и т. Д.), Но я не могу полностью избавиться от ощущения, что существует более элегантное решение этой проблемы. Кроме того, я хорошо осведомлен о межпроцессных и iostream-шаблонах Boost, хотя они кажутся довольно легковесными и требуют примерно столько же усилий при написании системы, использующей только вызовы Windows API (не говоря уже о том, что у меня уже есть память). сопоставленная архитектура, частично реализованная с использованием вызовов Windows API).
Я пытаюсь обработать большие наборы данных. Программа зависит от предварительно скомпилированных 32-битных библиотек, поэтому на данный момент сама программа также работает в 32-битном процессе, даже если система 64-битная, с 64-битной ОС. Я знаю, что есть способы, которыми я мог бы добавить библиотеки-обертки вокруг этого, но, учитывая, что это часть большей кодовой базы, это действительно было бы немного трудоемко. Я установил двоичные заголовки, чтобы учесть /LARGEADDRESSAWARE
(за счет уменьшения пространства моего ядра?), так что я получаю до 2-3 ГБ адресуемой памяти на процесс, отдачу или извлечение (в зависимости от фрагментации кучи и т. д.).
Вот в чем проблема: наборы данных имеют размер 4+ ГБ и имеют на них алгоритмы DSP, которые требуют, по существу, произвольного доступа ко всему файлу. Указатель на объект, сгенерированный из файла, обрабатывается в C #, но сам файл загружается в память (с помощью этой системы с частичным отображением памяти) в C ++ (это P / Invoked). Таким образом, я считаю, что решение, к сожалению, не так просто, как простая настройка окон для доступа к той части файла, к которой мне нужно получить доступ, поскольку, по сути, я хочу, чтобы весь файл абстрагировался в один указатель, из которого я могу вызывать методы для доступа к данным практически в любом месте файла.
Очевидно, что большинство архитектур с отображением в памяти полагается на разделение единственного процесса на несколько процессов … поэтому, например, я бы получил доступ к файлу размером 6 ГБ с процессами 3x, каждый из которых содержит окно размером 2 ГБ. Затем мне нужно было бы добавить значительное количество логики для извлечения и рекомбинации данных из этих разных окон / процессов. VirtualAllocEx
по-видимому, предоставляет метод увеличения виртуального адресного пространства, но я все еще не совсем уверен, является ли это наилучшим способом решения этой проблемы.
Но, скажем, я хочу, чтобы эта программа работала так же «легко», как отдельный 64-битный процесс в 64-битной системе. Предположим, что меня не волнует перегрузка, я просто хочу иметь возможность манипулировать большим файлом в системе, даже если в физический ОЗУ одновременно загружено, скажем, 500 МБ. Есть ли какой-нибудь способ получить эту функциональность без необходимости писать несколько нелепую ручную систему памяти вручную? Или, может быть, есть какой-то лучший способ, чем то, что я нашел, таким образом расчесывая SO и Интернет?
Это поддается вторичному вопросу: существует ли способ ограничения того, сколько физической оперативной памяти будет использоваться этим процессом? Например, что если я захочу ограничить процесс загрузкой только 500 МБ в физическую ОЗУ одновременно (при этом файл размером в несколько ГБ будет выгружен на диск)?
Я прошу прощения за длинный вопрос, но я чувствую, что это приличное резюме того, что кажется многими вопросами (только с частичными ответами), которые я нашел в SO и сети в целом. Я надеюсь, что это может быть область, в которой может быть найден окончательный ответ (или, по крайней мере, некоторые плюсы / минусы), и мы все можем узнать что-то ценное в процессе!
Вы можете написать класс доступа, которому вы дадите базовый адрес и длину. Он возвращает данные или выдает исключение (или, в противном случае, вы хотите сообщить об условиях ошибки), если возникают условия ошибки (за пределами и т. Д.).
Затем в любое время, когда вам нужно прочитать из файла, объект доступа может использовать SetFilePointerEx()
перед звонком ReadFile()
, Затем вы можете передать класс средства доступа в конструктор любых объектов, которые вы создаете при чтении файла. Затем объекты используют класс доступа для чтения данных из файла. Затем он возвращает данные конструктору объекта, который анализирует их в данных объекта.
Если позже вы сможете скомпилировать в 64-битную версию, вы можете просто изменить (или расширить) класс средства доступа для чтения из памяти.
Что касается ограничения количества оперативной памяти, используемой процессом .. это в основном вопрос того, чтобы убедиться, что
А) у вас нет утечек памяти (особенно непристойных) и
Б) уничтожение объектов, которые вам не нужны в данный момент. Даже если вам это понадобится позже, но данные не изменятся … просто уничтожьте объект. Затем воссоздайте его позже, когда вам это понадобится, что позволит ему перечитать данные из файла.
Других решений пока нет …