2015-10-28 8 views
12

入力配列をnumpyのufuncへのオプションの引数として提供するのが一般的に安全ですか?例えば、私は、次の動作することを確認した:入力配列をufuncの `out`引数として渡します

>>> import numpy as np 
>>> arr = np.array([1.2, 3.4, 4.5]) 
>>> np.floor(arr, arr) 
array([ 1., 3., 4.]) 

配列型は、(numpy.floor()ためのフロートである)出力と互換性または同一のいずれかでなければならない、又はこれが起こる:

>>> 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'' 

したがって、適切な型の配列を使用すると、ufuncをインプレースで適用するのは一般的に安全ですか?または、例外的なケースであるfloor()ですか? EDIT

  1. Numpy modify array in place?
  2. Numpy Ceil and Floor "out" Argument

:として

をドキュメントには、それを明確にしないと、どちらも質問に接線方向のベアリングを持って、次の二つのスレッドを実行しません。最初の推測では、http://docs.scipy.org/doc/numpy/user/c-info.ufunc-tutorial.htmlのチュートリアルに基づいて、それがよくあるとは限りませんが、必ずしも安全ではないと思います。計算中に中間結果の一時的な保持者として出力配列を使用することには何の制限もないようです。 floor()ciel()のようなものは一時的な格納を必要としないかもしれませんが、より複雑な機能があるかもしれません。つまり、既存のライブラリ全体を念頭に置いて書くことができます。

+2

これは技術的にufuncではありませんが、このようにして 'np.dot'の' out'パラメータを使用すると、2D配列で不正な結果が生じる可能性があります。 –

+0

これは、私が探していた反例とほぼ同じですが、それほどではありません:) –

+3

[ufunc docs](http://docs.scipy.org/doc/numpy/reference/ufuncs.html)の 'add(G、 C、G) 'を' G = G + C'の最適化として使用します。私はそれが安全だと言いたい。 (一方で、入力と出力が重複していても同じではない* ufuncsを呼び出すと問題が発生します) – user2357112

答えて

2

numpy関数のパラメータoutは、結果が書き込まれる配列です。 outを使用する主な利点は、必要でない新しいメモリの割り当てを避けることです。

入力と同じ配列にある関数の出力を書き出すことは安全ですか?一般的な答えはなく、関数が何をしているかによって異なります。

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の場合:期待される結果がここ

二つの例

はufuncのような機能の2つの例がありますパラメータxとoutが同じ配列である場合に得られます。アウトパラメータxと同じアレイである場合には機能shift_oneは、驚くべき結果を与えるので、アレイ

議論

形態 out[i] := some_operation(x[i])の機能について

、上記だけでなく、機能の床、CEIL、罪などplus_one私はそれが安全であることを知っている限り、パラメータ出力を使用して入力に結果を書き込むことができます。

またアウト形式の2つの入力パラメータ `[i]を取る関数の安全ある:= some_operation(X [i]は、Y [i])と、このようなnumpyの機能追加、乗算、減算などを。

他の機能については、大文字と小文字が区別されます。図示の怒鳴るように、行列の乗算は安全ではありません。

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]]) 

最終発言:実装がマルチスレッド化されている場合、それはどの順序に依存しているため、危険な関数の結果であっても非決定論的であり配列要素が処理されます。

関連する問題