3
import numpy as np

序文:

これはすでに知っているので、読むのに飽きたら序文を飛ばしてください。

最近、デバッグ中に問題に遭遇しました。`A = B = C = np.zeros([3,3]) と書いて、3 つの新しい行列を定義したと思っていました。私がしたことは実際には異なっていました。1 つの新しい行列 (ゼロで埋められた) と 3 つのラベルを定義し、それぞれが同じ行列を参照しています。次の例で説明しましょう。

>>> a = b = [0,0]
>>> a
[0,0]
>>> b
[0,0]
>>> # All good so far.
>>> a[0] = 1
>>> a
[1,0]
>>> # Nothing short of what one would expect...
>>> b
[1,0]
>>> # ... but since 'b' is assigned tot he same tuple, it changes as well.

質問:

良い。わかったからには、問題ないですよね?確かに私はちょうど書くことができます:

A = np.zeros([3,3])
B = np.zeros([3,3])
C = np.zeros([3,3])

そしてすべてが機能しますか?そのとおりですが、次のように書くこともできます。

A, B, C = np.zeros([3,3,3])

2 番目のオプションは、3x3x3 テンソルを定義し、レイヤーごとに 3 つのラベル A、B、C を定義するため、より効率的な方法でメモリを使用すると思います。

どっちがいいと思いますか?

4

2 に答える 2

3

何よりも、時期尚早の最適化の匂いがします。少数の行列について話している場合、どちらの方法でも問題ありません。多数の行列について話している場合、アンパックを利用する可能性は低いです。

そうは言っても、2 番目のオプションでは、より大きな基になるストレージを作成する必要がありますが、最初のオプションでは 3 つの個別のストレージを作成します。前者は、3 つのマトリックスすべてが同じ有効期間を共有する場合、いくらか効率的です。後者の方が読みやすく、個々の行列のメモリを解放できます。この種の最適化が重要な場合は、測定してください。

于 2013-07-08T16:20:29.093 に答える
3

2 つのケース (以下のコードと結果) で何が起こっているかを確認するための簡単なテストを行いました。疑わしいように、後者のアプローチはメモリを線形に割り当てますが、前者はシステムによって許可されている場所にメモリを分散させます(以前よりも厳密になると予想していました)。したがって、後者はメモリ位置の点でより効率的です。しかし、割り当て時間 (以下のスクリプトのタイミング) に関しては、それらは同等です (アンパックに時間がかかるようで、ほとんど非常に小さい数値について話している)。したがって、これについて考えるのは、おそらく時期尚早の最適化です。

import sys
import numpy as np
nr = 1000
rounds =1000
if len(sys.argv)==2:
    if sys.argv[1]=='seq':
        print "testing sequential allocation"
        for i in xrange(rounds):
            a=np.zeros([nr,nr])
            b=np.zeros([nr,nr])
            c=np.zeros([nr,nr])
    elif sys.argv[1]=='all':
        print "testing allocating all at once"
        for i in xrange(rounds):
            A,B,C=np.zeros([3,nr,nr])
        
        
a=np.zeros([3,3])
b=np.zeros([3,3])
c=np.zeros([3,3])
A,B,C=np.zeros([3,3,3])

print "diff in location b-a", b.__array_interface__['data'][0]-a.__array_interface__['data'][0]
print "diff in location c-a", c.__array_interface__['data'][0]-a.__array_interface__['data'][0]
print "diff in location B-A", B.__array_interface__['data'][0]-A.__array_interface__['data'][0]
print "diff in location C-A", C.__array_interface__['data'][0]-A.__array_interface__['data'][0]

出力

> 場所の違い ba -125520

>場所の違い ca -173376

> BA 72 の位置が異なる

>場所 CA 144 の違い

于 2013-07-08T16:21:11.310 に答える