Отображение памяти огромного файла в 32-битном программном обеспечении, работающем на 64-битной ОС

У меня проблемы с производительностью при чтении огромных файлов. Я хотел бы использовать отображение памяти для решения проблем. Входные файлы имеют размер до 10 ГБ, моя программа (написанная на C++) построена с 32-битной конфигурацией, целевой системой является 64-битная Windows и 24 ГБ ОЗУ. Возможно ли сопоставить весь огромный файл с памятью? Если да, то как моя программа может получить доступ к «высокой» адресной области (> 0xFFFFFFFF, теоретически, потому что моя программа 32-битная, поэтому указатели также 32-битные)?


person duong_dajgja    schedule 18.08.2015    source источник
comment
Есть ли причина, по которой вы не компилируете программу в 64 бита?   -  person NathanOliver    schedule 18.08.2015
comment
Программа написана давно. Он обновляется шаг за шагом, и 64-разрядная версия запланирована, но не сейчас.   -  person duong_dajgja    schedule 18.08.2015
comment
Вы можете сопоставлять файл только фрагментами, см. MSDN MapViewOfFile msdn.microsoft.com/en-us/library/windows/desktop/ . Обратите внимание, что он использует 2 DWORDS (высокий, низкий) в качестве смещения в файле, где должно начинаться представление. Попробуйте сопоставить ‹ 2 ГБ за раз.   -  person Richard Critten    schedule 18.08.2015
comment
Как вы думаете, почему отображение памяти будет быстрее, чем обычный файловый ввод-вывод? Это может быть верно для определенных типов шаблонов доступа, но не верно в самых общих случаях.   -  person Adrian McCarthy    schedule 18.08.2015
comment
@AdrianMcCarthy: проверьте stackoverflow.com/questions/32047626/ для более подробной информации о моей проблеме   -  person duong_dajgja    schedule 19.08.2015


Ответы (2)


Вы не можете. 32-разрядная программа использует 32-разрядные указатели, размер которых не превышает 4 ГБ даже при работе в 64-разрядной ОС.

Одна вещь, которая может немного помочь, это связать вашу программу с /LARGEADDRESSAWARE< /а> вариант. По умолчанию 32-разрядные программы Windows могут использовать только 2 ГБ адресного пространства, поскольку некоторые программы предполагают, что самый старший бит указателя всегда равен нулю, и используют его как флаг для хранения дополнительной информации. Это сломается, если Windows начнет выделять память выше 2 ГБ, поэтому вам нужно связать свою программу со специальной опцией, которая сообщает Windows, что ваша программа не злоупотребляет этим битом. Это позволяет вашей программе использовать все 4 ГБ адресного пространства вместо ограничения 2 ГБ.

person Wyzard    schedule 18.08.2015
comment
Я предполагаю, что единственные программы, которые настолько сильно злоупотребляют старшим битом и настолько значительны, что MSVC резервирует для них верхний бит, должны быть написаны самими людьми из MS. - person user3528438; 18.08.2015
comment
Первый абзац хорош, но тот, что в /LARGEADDRESSAWARE, вводит в заблуждение и не имеет отношения к делу. В лучшем случае /LARGEADDRESSAWARE получает 32-разрядный процесс 3 ГБ полезного адресного пространства, поскольку верхний ГБ по-прежнему зарезервирован для системы, как и некоторые фрагменты в середине, поэтому даже с /LARGEADDRESSAWARE у вас все равно не будет больше, чем 2 ГБ непрерывного пространства, что не поможет duong_dajgja загрузить файл размером 10 ГБ. - person Adrian McCarthy; 18.08.2015
comment
@AdrianMcCarthy, разделение 3 ГБ/1 ГБ предназначено для 32-разрядных окон с использованием /3GB вариант загрузки. 64-битной Windows не нужен этот гигабайт в верхней части 32-битного адресного пространства, поэтому 32-разрядные программы с поддержкой больших адресов могут использовать полные 4 ГБ. (Однако я не знаю, всегда ли Windows размещает данные в середине адресного пространства.) - person Wyzard; 19.08.2015
comment
@Wyzard: это заблуждение, потому что некоторые программы предполагают, что самый старший бит указателя всегда равен нулю, и используют его как флаг для хранения дополнительной информации. Это не имеет значения, потому что 3 или 4 ГБ непоследовательного адресного пространства все равно не помогут вам отобразить файл размером 10 ГБ. - person Adrian McCarthy; 19.08.2015

В 32-битной программе вы никогда не сможете отобразить весь файл сразу в одном процессе, так как длина адресного пространства составляет 2 ГБ. Что возможно, так это отображать только часть файла в данный момент, играя с MapViewOfFile параметрами. Также возможно сопоставить весь файл одновременно с несколькими процессами, отображающими по 1 ГБ каждый (поскольку отдельные процессы имеют разные адресные пространства), но это было бы действительно непрактично.

person ElderBug    schedule 18.08.2015
comment
Как вы сказали, для одного процесса адресное пространство имеет длину 2 ГБ, возможно ли для карты процесса 2 разных файла с длиной каждого файла 1,5 ГБ? - person duong_dajgja; 18.08.2015
comment
@duong_dajgja Нет, с адресным пространством 2 ГБ вы не можете сопоставить более 2 ГБ. Как вы упомянули, проблема не в памяти, а в доступе к ней. 2x1.5GB не влезут в адресное пространство. Вы можете добиться успеха, если сможете получить адресное пространство 4 ГБ, как упоминалось в ответе Wyzard. - person ElderBug; 18.08.2015