问题描述
只要类型正确,将输入数组作为ufunc中的ufunc的可选out参数提供,通常是安全的吗?例如,我已经验证了以下功能:
Is it generally safe to provide the input array as the optional out argument to a ufunc in numpy, provided the type is correct? For example, I have verified that the following works:
>>> import numpy as np
>>> arr = np.array([1.2, 3.4, 4.5])
>>> np.floor(arr, arr)
array([ 1., 3., 4.])
数组类型必须与输出兼容或相同(对于numpy.floor()
是浮点型),否则会发生这种情况:
The array type must be either compatible or identical with the output (which is a float for numpy.floor()
), or this happens:
>>> arr2 = np.array([1, 3, 4], dtype = np.uint8)
>>> np.floor(arr2, arr2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ufunc 'floor' output (typecode 'e') could not be coerced to provided output parameter (typecode 'B') according to the casting rule ''same_kind''
因此,考虑到适当类型的数组,通常就地应用ufuncs是否安全?还是floor()
是例外情况?该文档没有明确说明,与问题有切线关系的以下两个线程也没有:
So given that an array of proper type, is it generally safe to apply ufuncs in-place? Or is floor()
an exceptional case? The documentation does not make it clear, and neither do the following two threads that have tangential bearing on the question:
- Numpy modify array in place?
- Numpy Ceil and Floor "out" Argument
根据 http://docs.scipy.org/doc/numpy/user/c-info.ufunc-tutorial.html .在计算过程中,使用输出数组作为中间结果的临时持有者似乎没有任何限制.虽然floor()
和ciel()
之类的内容可能不需要临时存储,但可能需要更复杂的功能.话虽这么说,整个现有库可能是在考虑这一点的情况下编写的.
As a first order guess, I would assume it is often, but not always safe, based on the tutorial at http://docs.scipy.org/doc/numpy/user/c-info.ufunc-tutorial.html. There does not appear to be any restriction on using the output array as a temporary holder for intermediate results during the computation. While something like floor()
and ciel()
may not require temporary storage, more complex functions might. That being said, the entire existing library may be written with that in mind.
推荐答案
numpy函数的out
参数是写入结果的数组.使用out
的主要优点是避免在不必要的情况下分配新内存.
The out
parameter of a numpy function is the array where the result is written. The main advantage of using out
is avoiding the allocation of new memory where it is not necessary.
将函数的输出写在作为输入传递的同一数组上是否安全?没有通用的答案,这取决于函数的功能.
Is it safe to use write the output of a function on the same array passed as input? There is no general answer, it depends on what the function is doing.
以下是类似ufunc的函数的两个示例:
Here are two examples of ufunc-like functions:
In [1]: def plus_one(x, out=None):
...: if out is None:
...: out = np.zeros_like(x)
...:
...: for i in range(x.size):
...: out[i] = x[i] + 1
...: return out
...:
In [2]: x = np.arange(5)
In [3]: x
Out[3]: array([0, 1, 2, 3, 4])
In [4]: y = plus_one(x)
In [5]: y
Out[5]: array([1, 2, 3, 4, 5])
In [6]: z = plus_one(x, x)
In [7]: z
Out[7]: array([1, 2, 3, 4, 5])
功能shift_one
:
In [11]: def shift_one(x, out=None):
...: if out is None:
...: out = np.zeros_like(x)
...:
...: n = x.size
...: for i in range(n):
...: out[(i+1) % n] = x[i]
...: return out
...:
In [12]: x = np.arange(5)
In [13]: x
Out[13]: array([0, 1, 2, 3, 4])
In [14]: y = shift_one(x)
In [15]: y
Out[15]: array([4, 0, 1, 2, 3])
In [16]: z = shift_one(x, x)
In [17]: z
Out[17]: array([0, 0, 0, 0, 0])
对于功能plus_one
,没有问题:当参数x和out是同一数组时,可以获得预期的结果.但是当参数x和out是同一数组时,函数shift_one
给出了令人惊讶的结果,因为该数组
For the function plus_one
there is no problem: the expected result is obtained when the parameters x and out are the same array. But the function shift_one
gives a surprising result when the parameters x and out are the same array because the array
对于形式为out[i] := some_operation(x[i])
的函数,例如上面的plus_one
,还可以说是函数floor,ceil,sin,cos,tan,log,conj等,据我所知安全使用参数out将结果写到输入中.
For function of the form out[i] := some_operation(x[i])
, such as plus_one
above but also the functions floor, ceil, sin, cos, tan, log, conj, etc, as far as I know it is safe to write the result in the input using parameter out.
对于采用两个格式为``out [i]:= some_operation(x [i],y [i])的两个输入参数的函数(例如numpy函数add,乘,减去.
It is also safe for functions taking two input parameters of the form ``out[i] := some_operation(x[i], y[i]) such as the numpy function add, multiply, subtract.
对于其他功能,视情况而定.如图所示,矩阵乘法是不安全的:
For the other functions, it is case-by-case. As illustrated bellow, the matrix multiplication is not safe:
In [18]: a = np.arange(4).reshape((2,2))
In [19]: a
Out[19]:
array([[0, 1],
[2, 3]])
In [20]: b = (np.arange(4) % 2).reshape((2,2))
In [21]: b
Out[21]:
array([[0, 1],
[0, 1]], dtype=int32)
In [22]: c = np.dot(a, b)
In [23]: c
Out[23]:
array([[0, 1],
[0, 5]])
In [24]: d = np.dot(a, b, out=a)
In [25]: d
Out[25]:
array([[0, 1],
[0, 3]])
最后说明::如果实现是多线程的,则不安全函数的结果甚至可能是不确定的,因为它取决于处理数组元素的顺序.
Last remark: if the implementation is multithreaded, the result of an unsafe function may even be non-deterministic because it depends on the order on which the array elements are processed.
这篇关于Numpy将输入数组作为ufunc的`out`参数传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!