2013-07-26 10 views
12

Ich habe Python immer mehr anstelle von c/C++ benutzt, weil es meine Programmierzeit um ein Vielfaches verkürzt. Zur gleichen Zeit, wenn ich große Datenmengen verarbeite, beginnt die Geschwindigkeit, mit der meine Python-Programme laufen, viel langsamer als in c. Ich frage mich, ob dies daran liegt, dass ich große Objekte/Arrays ineffizient nutze. Gibt es eine umfassende Anleitung nur, wie Speicher von numpy/python behandelt wird? Wenn Dinge als Referenz und wann als Wert übergeben werden, wenn Dinge kopiert werden und wenn nicht, welche Typen sind änderbar und welche nicht.python numpy und memory efficiency (pass by reference vs. value)

+9

"Faktor von wenigen" ist mein neuer technischer Begriff für das Gespräch mit nicht-technischem Personal darüber, warum wir zu Python wechseln sollten. – BlackVegetable

+4

[Dieser Beitrag] (http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference) hat eine göttliche Menge an relevanten Daten zu dieser Frage ... – jdero

+0

@jdero Das heißt, es verhält sich grundsätzlich identisch mit Java, richtig? – BlackVegetable

Antwort

1

Also werde ich EOL haben auf diese zu zitieren, weil ich seine Antwort denken sehr relevant ist: „von Wert passing“ :

3) Der letzte Punkt auf die Frage Titel zusammenhängt und "passing by reference" sind keine Konzepte, die in Python relevant sind. Die relevanten Konzepte sind stattdessen "veränderbares Objekt" und "unveränderliches Objekt". Listen sind änderbar, während Zahlen nicht sind, die erklärt, was Sie beobachten. Außerdem sind Ihre Objekte Person1 und bar1 veränderbar (deshalb können Sie das Alter der Person ändern). Sie können weitere Informationen über diese Begriffe in einem Text-Tutorial und einem Video Tutorial finden. Wikipedia hat auch einige (mehr technische) Informationen. Ein Beispiel zeigt den Unterschied des Verhaltens zwischen wandelbar und unveränderlich - answer by EOL

Im Allgemeinen ich Numpy/Scipy folgen diese gefunden haben; was noch wichtiger ist, sie sagen dir explizit in den Dokumenten, was passiert.

Zum Beispiel np.random.shuffle fragt nach einem Eingabearray und gibt None zurück, während np.random.permutation ein Array zurückgibt. Sie können deutlich sehen, welcher einen Wert im Gegensatz zu nicht hier zurückgibt.

Simiarly-Arrays haben eine Semantik für den Durchgang durch Referenz und im Allgemeinen finde ich Numpy/Scipy sehr effizient.

Ich denke, es ist fair zu sagen, dass, wenn es schneller zu verwenden ist pass-by-reference werden sie. Solange Sie die Funktionen so verwenden, wie die Dokumente sagen, sollten Sie keine signifikanten Probleme in Bezug auf die Geschwindigkeit haben.


Gibt es einen bestimmten Typ, nach dem Sie fragen?

+0

Danke für Ihre Antwort. Nein, es gibt nicht wirklich spezifische Typen, die ich in Erwägung zog; Ich suchte eher nach einer Antwort über allgemeine, optimale Codierungsstile, die für die Berechnungseffizienz verwendet werden sollten. Ich denke, dass dies nicht für Python existieren könnte, außer darauf, dass numpy/scipy-Methoden bereits optimiert sind. – DilithiumMatrix

+0

Sorry im Allgemeinen Python wurde für Leichtigkeit nicht Geschwindigkeit :) gemacht. Sie können jedoch Teile schreiben, die Sie in C "schnell" machen wollen, und sie in Python aufrufen, um schnelle Laufzeiten zu erreichen, oder es ist immer numply/scipy, wie Sie sagen.Auch die Erstellung von numpy/scipy für Ihren spezifischen Build kann helfen, diese weiter zu optimieren! –

8

Objekte in Python (und den meisten gängigen Sprachen) werden als Referenz übergeben.

Wenn wir beispielsweise numpy verwenden, sind "neue" Arrays, die durch Indizierung bestehender erstellt werden, nur Ansichten des Originals. Zum Beispiel:

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 haben eine praktische Methode, mit Ihren Fragen zu helfen, rief may_share_memory (obj1, obj2). Also:

>>> np.may_share_memory(vec_1, vec_2) 
True 

Nur vorsichtig sein, weil es `s möglich, dass das Verfahren Fehlalarme zurückzukehren (obwohl ich nie gesehen).

Am SciPy 2013 gab es ein Tutorial zu numpy (http://conference.scipy.org/scipy2013/tutorial_detail.php?id=100). Am Ende spricht der Typ ein wenig darüber, wie numpy Speicher verarbeitet. Sieh es dir an.

Als Faustregel gilt, dass Objekte fast nie als Wert übergeben werden. Sogar diejenigen, die auf einem anderen Objekt eingekapselt sind. Ein anderes Beispiel, wo eine Liste eine Tour macht:

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] 

Gruselig, nicht wahr? Wenn Sie das Zuweisungssymbol ("=") verwenden oder am Ende einer Funktion eins zurückgeben, erstellen Sie immer einen Zeiger auf das Objekt oder einen Teil davon. Objekte werden nur dupliziert, wenn Sie dies ausdrücklich tun, verwenden Sie eine Kopiermethode wie some_dict.copy oder array [:]. Zum Beispiel:

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

Haben Sie es?

+0

Ich denke, in Ihrem letzten Beispiel sollte 'my_object.original_list'' my_object.get_list() 'sein. Sie können auch hinzufügen, wie 'vec2 [:]' sich gegenüber 'vec2' verhält, wenn ihnen im ersten Beispiel ein Wert zugewiesen wird –

Verwandte Themen