Поменять массив данных в NumPy - PullRequest
1 голос
/ 31 марта 2012

У меня есть много больших многомерных массивов NP (2D и 3D), используемых в алгоритме. В этом есть множество итераций, и во время каждой итерации массивы пересчитываются путем выполнения вычислений и сохранения во временные массивы одинакового размера. В конце одной итерации содержимое временных массивов копируется в фактические массивы данных.

Пример:

global A, B # ndarrays
A_temp = numpy.zeros(A.shape)
B_temp = numpy.zeros(B.shape)
for i in xrange(num_iters):
    # Calculate new values from A and B storing in A_temp and B_temp...
    # Then copy values from temps to A and B
    A[:] = A_temp
    B[:] = B_temp

Это прекрасно работает, однако копировать все эти значения, когда A и B могут просто поменяться местами, кажется немного расточительным. Следующее поменяет местами массивы:

A, A_temp = A_temp, A
B, B_temp = B_temp, B

Однако могут быть другие ссылки на массивы в других областях, которые это не изменит.

Кажется, что NumPy может иметь внутренний метод для замены внутреннего указателя данных двух массивов, например numpy.swap(A, A_temp). Тогда все переменные, указывающие на A, будут указывать на измененные данные.

Ответы [ 3 ]

1 голос
/ 31 марта 2012

Возможно, вы могли бы решить эту проблему, добавив уровень косвенности.

У вас может быть класс "держатель массива".Все, что нужно сделать, это сохранить ссылку на базовый массив NumPy.Реализация дешевой операции подкачки для пары из них будет тривиальной.

Если все внешние ссылки относятся к этим объектам-держателям, а не напрямую к массивам, ни одна из этих ссылок не будет аннулирована свопом.

1 голос
/ 15 июля 2015

Я понимаю, что это старый вопрос, но для чего бы это ни стоило, вы также можете поменять данные между двумя буферами ndarray (без временной копии), выполнив своп xor:

A_bytes = A.view('ubyte')
A_temp_bytes = A.view('ubyte')
A_bytes ^= A_temp_bytes
A_temp_bytes ^= A_bytes
A_bytes ^= A_temp_bytes

Поскольку это было сделанов представлениях, если вы посмотрите на исходные массивы A и A_temp (какими бы ни были их первоначальные dtype), их значения должны быть правильно поменяны местами.Это в основном эквивалентно numpy.swap(A, A_temp), который вы искали.К сожалению, для этого требуется 3 цикла - если бы это было реализовано как ufunc (возможно, так и должно быть), это было бы намного быстрее.

0 голосов
/ 31 марта 2012

Несмотря на то, что ваш путь должен работать так же хорошо (я подозреваю, что проблема в другом месте), вы можете попробовать сделать это явно:

import numpy as np
A, A_temp = np.frombuffer(A_temp), np.frombuffer(A)

Нетрудно убедиться, что ваш метод работает также:

>>> import numpy as np
>>> arr = np.zeros(100)
>>> arr2 = np.ones(100)
>>> print arr.__array_interface__['data'][0], arr2.__array_interface__['data'][0]
152523144 152228040

>>> arr, arr2 = arr2, arr
>>> print arr.__array_interface__['data'][0], arr2.__array_interface__['data'][0]
152228040 152523144

... указатели успешно переключены

...