2013-07-26 11 views
12

私は最近、c/C++の代わりにpythonを使用してきました。同時に、大量のデータを処理しているとき、私のpythonプログラムの実行速度はcよりもかなり遅くなり始めます。私はこれが大きなオブジェクト/配列を非効率的に使っているのかどうか疑問に思います。 numpy/pythonによってメモリがどのように処理されるかについて包括的なガイドがありますか?物事が参照によって渡され、価値によって、物がコピーされるとき、そうでないとき、どのタイプが変更可能であり、そうでないかは渡されます。私は彼の答えは非常に関連性があると思うので、python numpyとメモリ効率(参照渡しと値渡し)

+9

"Factor of a few"は私がPythonに切り替える理由を技術者以外の人と話すための私の新しい専門用語です。 – BlackVegetable

+4

[この投稿](この記事)(http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference)は、この質問に関連するデータを大量に持っています... – jdero

+0

@jderoつまり、基本的にはJavaと全く同じように動作します。 – BlackVegetable

答えて

1

は、だから私は、この上のEOLを引用する必要がありますするつもりです:

3)最後の点は質問タイトルに関連している:「値渡し」 「参照渡し」は、 Pythonに関連する概念ではありません。関連するコンセプトは、代わりに「変更可能オブジェクト」と 「不変オブジェクト」です。リストは変更可能ですが、数字は表示されません。 はあなたの観察内容を説明しています。また、あなたのPerson1とbar1のオブジェクトは です(そのため、あなたはその人の年齢を変更できます)。 これらの概念についての詳細は、テキストチュートリアルとビデオ チュートリアルを参照してください。ウィキペディアには、(より技術的な)情報もあります。 ; numpyの/ scipyのダウンロードは、これらに従ってください私を見つけた一般的にanswer by EOL

- 例は変更可能と 不変 間の挙動の違いを示していますもっと重要なのは、何が起きているのかをドキュメントで明示的に伝えていることです。

たとえば、 np.random.shuffleは入力配列を要求し、Noneを返します。np.random.permutationは配列を返します。どちらが値を返すのか、ここにはないのかをはっきりと見ることができます。

シリアライ配列は参照渡しのセマンティクスを持ち、一般的にはNumpy/Scipyが非常に効率的であるとわかります。

pass-by-referenceを使用する方が速いとすれば、それは可能でしょう。ドキュメントが言うような機能を使用する限り、スピードに関して重大な問題はないはずです。


あなたが尋ねている特定のタイプはありますか?

+0

あなたの答えをありがとう。いいえ、実際に私が検討していたタイプはありません。私は、計算効率のために一般的で最適なコーディングスタイルについての答えを探していました。これは、numpy/scipyメソッドがすでに最適化されていることを信頼するだけでなく、これはPythonでは存在しないかもしれないと思います。 – DilithiumMatrix

+0

一般的に、Pythonは高速化しないために作られました。しかし、Cで素早くしたい部分を書くことができますし、Pythonで呼び出すことでランタイムを早くすることもできますし、あなたが言うように常にnumpy/scipyがあります。また、特定のビルドに対してnumpy/scipyをコンパイルすると、それらをさらに最適化するのに役立ちます! –

8

Python(およびほとんどの主流言語)のオブジェクトは参照として渡されます。

たとえば、numpyを使用すると、既存のインデックスを作成することによって作成された「新しい」配列は、元の表示のみになります。たとえば:

import numpy as np 

>>> vec_1 = np.array([range(10)]) 
>>> vec_1 
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 
>>> vec_2 = vec_1[3:] # let vec_2 be vec_1 from the third element untill the end 
>>> vec_2 
array([3, 4, 5, 6, 7, 8, 9]) 
>>> vec_2[3] = 10000 
array([3, 4, 5, 10000, 7, 8, 9]) 
>>> vec_1 
array([0, 1, 2, 3, 4, 5, 10000, 7, 8, 9]) 

numpyのはmay_share_memory(OBJ1、OBJ2)と呼ばれるご質問を支援する便利な方法を、持っています。だから:

偽陽性を返すことが可能なので(私は一度も見たことはありませんが)、注意してください。

SciPy 2013には、numpy(http://conference.scipy.org/scipy2013/tutorial_detail.php?id=100)に関するチュートリアルがありました。最後に、この男は、いかんせんがどのように記憶を扱うかについて少し話します。見て。

経験則として、オブジェクトはデフォルトでほとんど値として渡されません。それらのオブジェクトも別のオブジェクトにカプセル化されています。リストがツアーを行う別の例:

Class SomeClass(): 

    def __init__(a_list): 
     self.inside_list = a_list 

    def get_list(self): 
     return self.inside_list 

>>> original_list = range(5) 
>>> original_list 
[0,1,2,3,4] 
>>> my_object = SomeClass(original_list) 
>>> output_list = my_object.get_list() 
>>> output_list 
[0,1,2,3,4] 
>>> output_list[4] = 10000 
>>> output_list 
[0,1,2,3,10000] 
>>> my_object.original_list 
[0,1,2,3,10000] 
>>> original_list 
[0,1,2,3,10000] 

不気味な、そうですか? 割り当てシンボル( "=")を使用するか、関数の最後に1つを返すと、オブジェクトまたはその一部へのポインタが常に作成されます。 オブジェクトは、明示的にdo_dict.copyやarray [:]のようなコピーメソッドを使用してを明示的に実行した場合にのみ複製されます。例:

>>> original_list = range(5) 
>>> original_list 
[0,1,2,3,4] 
>>> my_object = SomeClass(original_list[:]) 
>>> output_list = my_object.get_list() 
>>> output_list 
[0,1,2,3,4] 
>>> output_list[4] = 10000 
>>> output_list 
[0,1,2,3,10000] 
>>> my_object.original_list 
[0,1,2,3,10000] 
>>> original_list 
[0,1,2,3,4] 

これはありますか?

+0

あなたの最後の例では、 'my_object.original_list'は' my_object.get_list() 'でなければなりません。また、最初の例で値が割り当てられているときに 'vec2 [:]'が 'vec2'と比較してどのように動作するかを追加することもできます –