Astropy: Bug de memmap de possíveis ajustes: memmap simplesmente não funciona.

Criado em 26 ago. 2013  ·  12Comentários  ·  Fonte: astropy/astropy

Estou tentando carregar algumas tabelas de registros FITS gigantescas usando memmap=True e estou recebendo error: [Errno 12] Cannot allocate memory .

Um exemplo de sessão:

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]

O erro está nesta linha:

/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

Eu realmente não sei o que está acontecendo, mas suspeito que o memmap está decidindo indevidamente a quantidade de dados a ser lida. Alguma dica sobre como depurar ainda mais? É realmente um problema do FITS ou um problema entorpecido?

Detalhes:

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

Todos 12 comentários

Qual sistema operacional?

O que ulimit -v retorna?

OS é uma espécie de linux; não sei de cara ou o
comando mais fácil de descobrir.

Além disso, estava usando a instalação do anaconda de python / astropy / numpy, mas atualizado
astropia via pip.

$ ulimit -v
ilimitado

Na terça-feira, 27 de agosto de 2013 às 16h02, Erik Bray [email protected] escreveu:

Qual sistema operacional?

O que ulimit -v retorna?

-
Responda a este e-mail diretamente ou visualize-o em Gi tHubhttps: //github.com/astropy/astropy/issues/1380#issuecomment -23374814
.

Adão

O que cat /proc/meminfo mostra?

$ 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

... isso parece uma pequena quantidade de memória; 2 GB? Hrmph.

@keflavich - você ainda está vendo esse problema?

Esqueci-me totalmente disso. MemTotal é apenas a memória física total disponível. Esses 2 GB não são muito, com certeza, mas esse não deveria ser o problema. Você tem cerca de 32 TB para VmallocTotal que é o que deve importar aqui - em princípio, o mmap deve ser capaz de usar a maior parte disso. Portanto, há algo estranho acontecendo aqui.

Ah! Acho que vejo o problema aqui. Por padrão, o PyFITS usa MAP_PRIVATE ao abrir um arquivo no modo somente leitura para que os usuários ainda possam modificar a matriz de dados no local como fariam se o arquivo inteiro fosse mapeado na memória principal.

O problema é que, em princípio, o arquivo inteiro pode ser sobrescrito, então o mmap precisa ser capaz de alocar memória suficiente com antecedência, caso isso ocorra. É por isso que isso está acontecendo aqui. PyFITS / Astropy definitivamente deve capturar esse cenário e fornecer um erro mais útil.

Atualmente, existem duas maneiras de contornar isso: Você pode abrir o arquivo com mode='denywrite . Eu adicionei isso há um tempo especificamente para este caso, mas raramente é usado. Isso abre o mmap com MAP_SHARED | PROT_READ - isso significa que as páginas são somente leitura (qualquer tentativa de modificar o array resultará em uma exceção). Mas se tudo que você precisa é ler os dados, isso funciona bem e não requer a alocação de nenhum espaço de swap, eu não acho.

Outra possibilidade é abrir com mode='update' . Então, quaisquer alterações no array podem ser sincronizadas diretamente de volta para o arquivo, o que é bom se você quiser, mas obviamente não tanto se não quiser.

Olhando a página do manual, parece que também há um sinalizador, pelo menos no Linux, chamado MAP_NORESERVE que o impedirá de pré-alocar espaço para cópia na gravação. Portanto, se você não _precisa_ gravar nenhuma alteração em todo o array, isso também pode funcionar. Mas teríamos que ser capazes de capturar o SIGSEGV resultante se você acabar ficando sem espaço de troca.

Consegui reproduzir isso diretamente - na verdade, ambas as soluções alternativas que ofereci ( mode='denywrite' e mode='update' funcionam. Ainda tentarei ver o que posso fazer sobre MAP_NORESERVE e de outra forma capturar esse erro e fornecer uma mensagem de erro melhor.

Aborrecimento: numpy.memmap não permite ajustes nos sinalizadores que são passados ​​para a chamada mmap . Embora olhando para ele, não é muito mais do que uma leve subclasse de ndarray que lida com o trabalho de criar um mmap com os sinalizadores corretos e, em seguida, chamar ndarray.__new__ com o mmap como seu buffer. Ele também adiciona um método flush .

Deve ser fácil simplesmente evitar o uso de numpy.memmap e lidar com o mmap nós mesmos. Mas isso ainda é mais do que eu quero fazer agora. Portanto, em vez disso, resolverei esse problema identificando o erro e sugerindo uma das soluções alternativas existentes.

Observe que com # 7597 não usamos mais np.memmap , então deve ser mais fácil usar outros sinalizadores se isso for útil.

Isso agora pode ser fechado, pois uma solução alternativa foi mesclada em https://github.com/astropy/astropy/pull/7926. MAP_NORESERVE não está disponível no Python, portanto, essa não é uma solução, infelizmente.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

pllim picture pllim  ·  3Comentários

richardgmcmahon picture richardgmcmahon  ·  3Comentários

bmorris3 picture bmorris3  ·  3Comentários

JWDobken picture JWDobken  ·  3Comentários

pllim picture pllim  ·  3Comentários