numpy memmap изменить файлы

У меня проблема с пониманием того, как работает numpy.memmap. Предыстория заключается в том, что мне нужно уменьшить большой массив numpy, сохраненный на диске, путем удаления записей. Чтение массива и построение нового путем копирования нужных частей не работает — он просто не помещается в память. Итак, идея состоит в том, чтобы использовать numpy.memmap, то есть работать с диском. Это мой код (с небольшим файлом):

import numpy

in_file = './in.npy'
in_len = 10
out_file = './out.npy'
out_len = 5

# Set up input dummy-file
dummy_in = numpy.zeros(shape=(in_len,1),dtype=numpy.dtype('uint32'))
for i in range(in_len):
    dummy_in[i] = i + i
numpy.save(in_file, dummy_in)

# get dtype and shape from the in_file
in_npy = numpy.load(in_file)

in_dtype = in_npy.dtype
in_shape = (in_npy.shape[0],1)
del(in_npy)

# generate an 'empty' out_file with the desired dtype and shape
out_shape = (out_len,1)
out_npy = numpy.zeros(shape=out_shape, dtype=in_dtype)
numpy.save(out_file, out_npy)
del(out_npy)

# memmap both files
in_memmap = numpy.memmap( in_file,  mode='r',  shape=in_shape, dtype=in_dtype)
out_memmap = numpy.memmap(out_file, mode='r+', shape=out_shape, dtype=in_dtype)
print "in_memmap"
print in_memmap, "\n"
print "out_memmap before in_memmap copy"
print out_memmap, "\n"

# copy some parts
for i in range(out_len):
    out_memmap[i] = in_memmap[i]

print "out_memmap after in_memmap copy"
print out_memmap, "\n"
out_memmap.flush()

# test
in_data = numpy.load(in_file)
print "in.npy"
print in_data
print in_data.dtype, "\n"

out_data = numpy.load(out_file)
print "out.npy"
print out_data
print out_data.dtype, "\n"

Запустив этот код, я получаю:

in_memmap
[[1297436307]
 [     88400]
 [ 662372422]
 [1668506980]
 [ 540682098]
 [ 880098343]
 [ 656419879]
 [1953656678]
 [1601069426]
 [1701081711]]

out_memmap before in_memmap copy
[[1297436307]
 [     88400]
 [ 662372422]
 [1668506980]
 [ 540682098]]

out_memmap after in_memmap copy
[[1297436307]
 [     88400]
 [ 662372422]
 [1668506980]
 [ 540682098]]

in.npy
[[ 0]
 [ 2]
 [ 4]
 [ 6]
 [ 8]
 [10]
 [12]
 [14]
 [16]
 [18]]
uint32

out.npy
[[0]
 [0]
 [0]
 [0]
 [0]]
uint32

Из вывода видно, что я делаю что-то не так:

1) memmap не содержат значений, заданных в массивах, а in_memmap и out_memmap содержат одинаковые значения.

2) Неясно, копирует ли команда копирования что-либо из in_memmap в out_memmap (из-за идентичных значений). Проверяя в режиме отладки значения in_memmap[i] и out_memmap[i], я получаю для обоих: memmap([1297436307], dtype=uint32). Итак, я могу назначить их, как в коде, или мне нужно использовать: out_memmap[i][0] = in_memmap[i][0]?

3) out.npy не обновляется до значений out_memmap операцией flush().

Может ли кто-нибудь помочь мне понять, что я делаю неправильно здесь.

Большое спасибо


person fdiehl    schedule 08.08.2017    source источник
comment
Ваша проблема заключается в том, что np.save и np.memmap имеют немного разные форматы. Проверьте этот ответ   -  person Daniel F    schedule 08.08.2017
comment
Кроме того, если вы регулярно используете массивы больше, чем может выдержать ваша оперативная память, проверьте dask.   -  person Daniel F    schedule 08.08.2017


Ответы (1)


Замените каждый экземпляр np.memmap на np.lib.format.open_memmap и получите:

in_memmap 
[[ 0]
 [ 2]
 [ 4]
 [ 6]
 [ 8]
 [10]
 [12]
 [14]
 [16]
 [18]] 

out_memmap before in_memmap copy 
[[0]
 [0]
 [0]
 [0]
 [0]] 

out_memmap after in_memmap copy 
[[0]
 [2]
 [4]
 [6]
 [8]] 

in.npy 
[[ 0]
 [ 2]
 [ 4]
 [ 6]
 [ 8]
 [10]
 [12]
 [14]
 [16]
 [18]] 
 uint32 

out.npy 
[[0]
 [2]
 [4]
 [6]
 [8]] 
 uint32 

np.save добавляет заголовок, который читал np.memmap, поэтому данные в обоих выглядели одинаково (поскольку это один и тот же заголовок). Именно поэтому, когда вы копировали данные из одного в другой, это не имело никакого эффекта (поскольку копировались только заголовки, а не данные) np.lib.format.open_memmap автоматически пропускает заголовок, чтобы вы могли работать с данными.

person Daniel F    schedule 08.08.2017