タイプが正しい場合、入力配列をnumpyの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()
例外的なケースですか?ドキュメントはそれを明確にしておらず、質問に正接する次の2つのスレッドも行いません。
編集:
一次推測として、http://docs.scipy.org/doc/numpy/user/c-info.ufunc-tutorial.htmlのチュートリアルに基づいて、常に安全ではないことが多いと思います。計算中の中間結果の一時的なホルダーとして出力配列を使用することに制限はないようです。一時的なストレージのようなものfloor()
やciel()
必要としないものもありますが、より複雑な機能が必要になる場合があります。そうは言っても、既存のライブラリ全体がそのことを念頭に置いて作成されている可能性があります。
out
numpy関数のパラメーターは、結果が書き込まれる配列です。使用の主な利点out
は、不要な場所での新しいメモリの割り当てを回避できることです。
入力として渡された同じ配列に関数の出力を書き込んで使用しても安全ですか?一般的な答えはありません。関数が何をしているかによって異なります。
次に、ufuncに似た関数の2つの例を示します。
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が同じ配列の場合、期待される結果が得られます。ただし、この関数shift_one
は、パラメーターxとoutが同じ配列である場合に驚くべき結果をもたらします。これは、配列
上記のようout[i] := some_operation(x[i])
なformの関数については、plus_one
floor、ceil、sin、cos、tan、log、conjなどの関数についても、パラメーターoutを使用して入力に結果を書き込んでも安全であることがわかっています。
また、numpy関数の加算、乗算、減算など、「out [i]:= some_operation(x [i]、y [i])」の形式の2つの入力パラメーターを取る関数も安全です。
その他の機能については、ケースバイケースです。以下に示すように、行列の乗算は安全ではありません。
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]])
最後の注意:実装がマルチスレッド化されている場合、安全でない関数の結果は、配列要素が処理される順序に依存するため、非決定的である可能性さえあります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加