2012-03-31 45 views
1

我有许多在算法中使用的大型多维NP阵列(2D和3D)。这里有很多迭代,在每次迭代期间,通过执行计算并保存到相同大小的临时数组中来重新计算数组。在一次迭代结束时,临时数组的内容被复制到实际的数据数组中。在NumPy中交换数组数据

例子:

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的所有变量都将指向已更改的数据。

+0

你可以举一个“其他范围内的数组的其他引用,这将不会改变”的例子吗? – dmytro 2012-03-31 09:49:53

+0

例如,对于计算步骤,我可以(并且将)具有多个线程,用一个函数调用,其中字段作为参数传递。为了减少实例化它们循环的多个线程的开销。 – coderforlife 2012-04-01 03:57:20

+0

如果我没有记错,除非您使用像sharedctypes数组等特定功能,否则无法在线程/进程之间传递数据。但我可能是错的...... – dmytro 2012-04-01 22:04:55

回答

1

也许你可以解决这个问题。

你可以有一个“数组持有者”类。所做的只是保留对底层NumPy数组的引用。实施一对便宜的交换操作将是微不足道的。

如果所有外部引用都是针对这些持有者对象而不是直接指向数组,则这些引用都不会因交换而失效。

+0

这绝对是一个可行的选择。这看起来很愚蠢,因为ndarray已经有了一个指向可以改变的适当数据的指针......如果我无法弄清楚使用视图的方式,这将是答案。 – coderforlife 2012-04-01 04:21:00

+0

@thaimin:交换两件事的Pythonic方法是'a,b = b,a'。这交换了参考。我想不出一个标准的类来实现一个你想要的交换界面。它只是没有在Python中完成,因为它几乎不需要。 – NPE 2012-04-01 06:24:13

+0

我明白了。我试图使用视图,如果它允许您重新分配“基本”字段,它将起作用。我试图分配几乎可以工作但不允许交换的“数据”字段(尽管第一个分配完全符合我的要求,而a.data,b.data = b.data,a.data不会交换“一”他们)。 – coderforlife 2012-04-04 04:07:23

0

即使你的方法应该工作一样好(我怀疑问题是其他地方),你可以尝试明确地做这件事:

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 

...指针通过增加间接层succsessfully切换

+0

frombuffer的想法很有趣,但它需要一个“重塑(A.shape)”命令它只返回一维数组。除此之外,尽管这不能解决替代引用的问题。我尝试了几个不同的东西,并且需要一个“setbuffer”函数......这让我有了一个想法,可以查看视图(我其实并不太了解太多)。 – coderforlife 2012-04-01 04:19:40

1

我意识到这是一个老问题,但对于它的价值,你也可以通过执行XOR交换交换两个ndarray缓存之间的数据(没有临时副本):因为这是做了

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 

意见,如果你看看原始AA_temp数组(无论他们的原始dtype是什么),它们的值应该被正确地交换。这基本上等于您要查找的numpy.swap(A, A_temp)。不幸的是,它需要3个循环 - 如果这是作为一个ufunc实现的(也许它应该是),它会快得多。