Wie skaliert sich die Leistung von Python / Numpy-Array-Operationen mit zunehmenden Array-Dimensionen?

21

Wie skalieren Python / Numpy-Arrays mit zunehmenden Array-Dimensionen?

Dies basiert auf einem Verhalten, das ich beim Benchmarking von Python-Code für diese Frage festgestellt habe: Wie kann man diesen komplizierten Ausdruck mit numpy-Slices ausdrücken?

Das Problem bestand hauptsächlich in der Indizierung zum Auffüllen eines Arrays. Ich fand heraus, dass die Vorteile der Verwendung von (nicht sehr guten) Cython- und Numpy-Versionen gegenüber einer Python-Schleife in Abhängigkeit von der Größe der beteiligten Arrays variieren. Sowohl Numpy als auch Cython verzeichnen einen zunehmenden Leistungsvorteil bis zu einem gewissen Punkt (ungefähr für Cython und N = 2000 für Numpy auf meinem Laptop), wonach ihre Vorteile nachließen (die Cython-Funktion blieb die schnellste).N=500N=2000

Ist diese Hardware definiert? Welche bewährten Methoden sollten beim Arbeiten mit großen Arrays für Code befolgt werden, bei dem die Leistung geschätzt wird?

Darstellung der Ausführungszeit relativ zu Schleifencode für vektorisierte und Cython-Implementierungen

Diese Frage ( Warum hängt meine Matrix-Vektor-Multiplikationsskalierung nicht zusammen? ) Mag zusammenhängen, aber ich bin daran interessiert, mehr darüber zu erfahren, wie verschiedene Arten der Behandlung von Arrays im Python-Maßstab im Verhältnis zueinander aussehen.

Nat Wilson
quelle
Haben Sie versucht, numexpr ? Es gibt zum Beispiel auch dieses Gerede, das auf blosc und CArray verweist , um die Dinge weiter zu beschleunigen (und möglicherweise die Speicherbandbreitenbeschränkungen zu umgehen).
0 0
1
Können Sie den zum Profilieren verwendeten Code posten? Hier ist wahrscheinlich einiges los.
Meawoppl

Antworten:

5

416kB

def timeit(size):
     t0 = time.time()
     for _ in xrange(10):
         np.random.random(size)
     return time.time() - t0

sizes = np.logspace(1, 6, 40)
times = [timeit(s) for s in sizes]

Es gibt ein paar Dinge, die mit diesem Benchmark nicht in Ordnung sind. Zunächst deaktiviere ich die Müllabfuhr nicht und nehme die Summe, nicht die beste Zeit, sondern trage sie mit mir.

800064kB

Sollte man sich über die Cache-Größe Gedanken machen? In der Regel sage ich nein. In Python dafür zu optimieren bedeutet, den Code für zweifelhafte Leistungssteigerungen viel komplizierter zu machen. Vergessen Sie nicht, dass Python-Objekte mehrere Overheads hinzufügen, die schwer zu verfolgen und vorherzusagen sind. Ich kann mir nur zwei Fälle vorstellen, in denen dies ein relevanter Faktor ist:

  • Grundlegende Operationen für große Arrays (wie das Auswerten eines Polynoms), begrenzt durch die Speicherbandbreite. Verwenden Sie Numexpr oder (wenn die Daten viel größer sind) Pytables . Sie sind optimiert, um unter anderem die Cache-Größe zu berücksichtigen.
  • Leistungskritischer Code: Wenn Sie jede Mikrosekunde komprimieren möchten, sollten Sie Python nicht in erster Linie verwenden. Wenn Sie vektorisiertes Cython schreiben und den Compiler das tun lassen, was er am besten kann, ist dies wahrscheinlich der schmerzlose Weg.

In den Kommentaren erwähnte Evert CArray. Beachten Sie, dass die Entwicklung auch bei laufendem Betrieb angehalten wurde und als eigenständiges Projekt aufgegeben wurde. Die Funktionalität wird stattdessen in Blaze integriert , einem laufenden Projekt zur Herstellung einer "neuen Generation von Numpy".

Davidmh
quelle