<p>Die Implementierung von numpy.vectorize ist im Wesentlichen eine for-Schleife.</p>

Erstellt am 6. Juli 2020  ·  5Kommentare  ·  Quelle: numpy/numpy

https://numpy.org/doc/1.18/reference/generated/numpy.vectorize.html
In diesem Tutorial wird erwähnt, dass die Implementierung von vectorize im Wesentlichen eine for-Schleife ist. Aber soweit ich weiß, wird eine vektorisierte Funktion verwendet
SIMD, ist es also richtig zu sagen, dass die Implementierung von numpy.vectorize im Wesentlichen eine for-Schleife ist? Wenn dies zutrifft, ist es nur schneller als die nicht enthüllte Funktion, nur weil die Schleife in der C-Sprache implementiert ist?

Vielen Dank im Voraus.

33 - Question

Hilfreichster Kommentar

Ja. Im Zusammenhang mit interpretierten numerischen Array-Programmiersprachen wie Python (mit Numpy) und MATLAB ™ verwenden wir häufig "Vektorisierung", um explizite Schleifen in der interpretierten Programmiersprache durch eine Funktion (oder einen Operator) zu ersetzen, die sich um alle Funktionen kümmert interne Schleifenlogik. In numpy implementieren die ufunc diese Logik. Dies hat nichts mit der Verwendung von "Vektorisierung" zu tun, um sich auf die Verwendung von SIMD-CPU-Anweisungen zu beziehen, die über mehrere Eingänge gleichzeitig berechnet werden, mit der Ausnahme, dass beide eine ähnliche Metapher verwenden: Sie sind wie ihre "skalaren" Gegenstücke, führen jedoch die Berechnung über mehrere Eingabewerte durch mit einem einzigen Aufruf.

Mit numpy.vectorize() gibt es normalerweise nicht viel Geschwindigkeitsvorteil gegenüber der expliziten Python for -Schleife. Der Hauptpunkt dabei ist, die Python-Funktion in ein ufunc , das die gesamte Broadcast-Semantik implementiert und somit jede Größe von Eingaben behandelt. Die Python-Funktion, die "vektorisiert" wird, nimmt immer noch die meiste Zeit in Anspruch und konvertiert den Rohwert jedes Elements in ein Python-Objekt, um es an die Funktion zu übergeben. Sie würden nicht erwarten, dass np.vectorize(lambda x, y: x + y) so schnell ist wie das ufunc np.add , das sowohl in der Schleife als auch im Inhalt der Schleife C ist.

Alle 5 Kommentare

Ja. Im Zusammenhang mit interpretierten numerischen Array-Programmiersprachen wie Python (mit Numpy) und MATLAB ™ verwenden wir häufig "Vektorisierung", um explizite Schleifen in der interpretierten Programmiersprache durch eine Funktion (oder einen Operator) zu ersetzen, die sich um alle Funktionen kümmert interne Schleifenlogik. In numpy implementieren die ufunc diese Logik. Dies hat nichts mit der Verwendung von "Vektorisierung" zu tun, um sich auf die Verwendung von SIMD-CPU-Anweisungen zu beziehen, die über mehrere Eingänge gleichzeitig berechnet werden, mit der Ausnahme, dass beide eine ähnliche Metapher verwenden: Sie sind wie ihre "skalaren" Gegenstücke, führen jedoch die Berechnung über mehrere Eingabewerte durch mit einem einzigen Aufruf.

Mit numpy.vectorize() gibt es normalerweise nicht viel Geschwindigkeitsvorteil gegenüber der expliziten Python for -Schleife. Der Hauptpunkt dabei ist, die Python-Funktion in ein ufunc , das die gesamte Broadcast-Semantik implementiert und somit jede Größe von Eingaben behandelt. Die Python-Funktion, die "vektorisiert" wird, nimmt immer noch die meiste Zeit in Anspruch und konvertiert den Rohwert jedes Elements in ein Python-Objekt, um es an die Funktion zu übergeben. Sie würden nicht erwarten, dass np.vectorize(lambda x, y: x + y) so schnell ist wie das ufunc np.add , das sowohl in der Schleife als auch im Inhalt der Schleife C ist.

Vielen Dank für Ihre ausführliche Erklärung. Aber um klar zu sein, lassen Sie mich ein Beispiel nehmen.

import pandas as pd
import numpy as np
df = pd.DataFrame({'a': range(100000), 'b': range(1, 1000001)})
# method1
df.loc[:, 'c'] = df.apply(lambda x: x['a'] + x['b'], axis=1)
# method2 
df.loc[:, 'c'] = np.vectorize(lambda x, y: x + y)(df['a'], df['b'])
# method3
df.loc[:, 'c'] = np.add(df['a'], df['b'])

Also mit deiner Erklärung, denke ich

Methode | Schleife in C | Schleifeninhalt in C | Verwenden Sie SIMD
- | - | - | - -
1 | × | × | ×
2 | √ | × | ×
3 | √ | √ | √

Recht?

np.add ist schneller als np.vectorize(lambda x, y: x + y) da die Konvertierung von C-Doubles in Python-Objekte und der Overhead des Python-Funktionsaufrufs vermieden werden. Es ist möglich, dass es auch SIMD-Anweisungen verwendet, je nachdem, ob Sie die AVX2-Erweiterungen haben oder nicht, aber das ist nicht der Grund, warum es schneller ist.

np.add ist schneller als np.vectorize(lambda x, y: x + y) da die Konvertierung von C-Doubles in Python-Objekte und der Overhead des Python-Funktionsaufrufs vermieden werden. Es ist möglich, dass es auch SIMD-Anweisungen verwendet, je nachdem, ob Sie die AVX2-Erweiterungen haben oder nicht, aber das ist nicht der Grund, warum es schneller ist.

Ich hab es geschafft. Vielen Dank.

Sie können vectorize von numba verwenden, um Ufuncs zu erstellen, die ohne Python-Overhead parallel arbeiten:

https://numba.pydata.org/numba-doc/latest/user/vectorize.html

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen