Astropy: Возможная ошибка соответствия memmap: memmap просто не работает.

Созданный на 26 авг. 2013  ·  12Комментарии  ·  Источник: astropy/astropy

Я пытаюсь загрузить несколько гигантских таблиц записей FITS, используя memmap=True , и получаю error: [Errno 12] Cannot allocate memory .

Пример сеанса:

filename = '/home/sdfits/AGBT12B_221_01/AGBT12B_221_01.raw.acs.fits'
import astropy.io.fits as fits
filefits = fits.open(filename,memmap=True)
data = filefits[2].data[:50]

Ошибка находится в этой строке:

/users/aginsbur/anaconda/lib/python2.7/site-packages/numpy/core/memmap.py(253)__new__()
--> 253             mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)

ipdb> bytes
23718381056L
ipdb> bytes/1024**2
22619L
ipdb> start
413921280
ipdb> acc
3

Я действительно не знаю, что происходит, но подозреваю, что memmap неправильно решает, сколько данных читать. Есть какие-нибудь советы по дальнейшей отладке? Действительно ли это проблема FITS или непонятная проблема?

Подробности:

In [15]: numpy.__version__
Out[15]: '1.7.1'

In [16]: astropy.__version__
Out[16]: '0.2.4'

In [18]: sys.maxint
Out[18]: 9223372036854775807
Bug Effort-medium Package-intermediate io.fits

Все 12 Комментарий

Какая ОС?

Что возвращает ulimit -v ?

ОС - это некоторая разновидность Linux; не знаю из головы или
самая простая команда, чтобы узнать.

Кроме того, использовалась установка anaconda для python / astropy / numpy, но была обновлена
астропия через пипс.

$ ulimit -v
неограниченный

27 августа 2013 г. в 16:02 Эрик Брей [email protected] написал:

Какая ОС?

Что возвращает ulimit -v?

-
Ответьте на это письмо напрямую или просмотрите его на Gi tHubhttps: //github.com/astropy/astropy/issues/1380#issuecomment -23374814
.

Адам

Что показывает cat /proc/meminfo ?

$ cat /proc/meminfo
MemTotal:        1903396 kB
MemFree:          203864 kB
Buffers:          215320 kB
Cached:           884708 kB
SwapCached:         2268 kB
Active:           492052 kB
Inactive:         954324 kB
Active(anon):     165684 kB
Inactive(anon):   181096 kB
Active(file):     326368 kB
Inactive(file):   773228 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       1048568 kB
SwapFree:        1031460 kB
Dirty:                24 kB
Writeback:             0 kB
AnonPages:        344352 kB
Mapped:            65676 kB
Shmem:               432 kB
Slab:             191348 kB
SReclaimable:     151148 kB
SUnreclaim:        40200 kB
KernelStack:        2312 kB
PageTables:        22940 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2000264 kB
Committed_AS:     847268 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      286128 kB
VmallocChunk:   34359439336 kB
HardwareCorrupted:     0 kB
AnonHugePages:     12288 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:        8188 kB
DirectMap2M:     2070528 kB

... это похоже на крошечный объем памяти; 2 ГБ? Хмф.

@keflavich - вы все еще

Совсем забыл об этом. MemTotal - это всего лишь общая доступная физическая память. Эти 2 ГБ - это немного, конечно, но это не должно быть проблемой. У вас есть около 32 ТБ на VmallocTotal что здесь должно иметь значение - в принципе mmap должен иметь возможность использовать большую часть этого. Так что здесь происходит что-то подозрительное.

Ах! Думаю, я вижу здесь проблему. По умолчанию PyFITS использует MAP_PRIVATE при открытии файла в режиме только для чтения, чтобы пользователи могли изменять массив данных на месте, как если бы весь файл был отображен в основную память.

Проблема в том, что в принципе это означает, что весь файл может быть перезаписан, поэтому mmap должен иметь возможность заранее выделить достаточно памяти, если это произойдет. Вот почему это происходит здесь. PyFITS / Astropy определенно должен отловить этот сценарий и предоставить более полезную ошибку.

В настоящее время есть два способа обойти это: Вы можете открыть файл с помощью mode='denywrite . Я добавил это некоторое время назад специально для этого случая, но он используется редко. Это открывает mmap с помощью MAP_SHARED | PROT_READ означает, что страницы доступны только для чтения (любая попытка изменить массив приведет к исключению). Но если все, что вам нужно, это прочитать данные, это отлично работает и не требует выделения места подкачки, я не думаю.

Другая возможность - открыть с помощью mode='update' . Затем любые изменения в массиве можно синхронизировать непосредственно с файлом, что нормально, если вы этого хотите, но, очевидно, не так много, если вы этого не сделаете.

Глядя на страницу руководства, похоже, что есть также флаг, по крайней мере в Linux, с именем MAP_NORESERVE который не позволяет заранее выделять пространство для копирования при записи. Так что, если вам не _ нужно_ записывать какие-либо изменения во весь массив, это тоже может сработать. Но мы должны быть в состоянии поймать SIGSEGV, который возникает, если у вас заканчивается пространство подкачки.

Удалось воспроизвести это напрямую - действительно, оба предложенных мной обходных пути ( mode='denywrite' и mode='update' работают. Я все равно буду пытаться посмотреть, что я могу сделать с MAP_NORESERVE , и в противном случае выявление этой ошибки и предоставление более точного сообщения об ошибке.

Раздражение: numpy.memmap не позволяет настраивать флаги, которые передаются вызову mmap . Смотря на это, это не более чем легкий подкласс ndarray который выполняет работу по созданию mmap с правильными флагами, а затем вызывает ndarray.__new__ с mmap в качестве его буфера. Он также добавляет метод flush .

Должно быть достаточно легко просто отказаться от использования numpy.memmap и обрабатывать mmap самостоятельно. Но это все еще больше, чем я хочу сейчас делать. Поэтому вместо этого я решу эту проблему, обнаружив ошибку и предложив один из существующих обходных путей.

Обратите внимание, что с # 7597 мы больше не используем np.memmap , поэтому будет проще использовать другие флаги, если это полезно.

Теперь это можно закрыть, так как обходной путь был объединен в https://github.com/astropy/astropy/pull/7926. MAP_NORESERVE недоступен в Python, поэтому, к сожалению, это не решение.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги