Gibt es eine Standardbibliothek / ein numpy-Äquivalent der folgenden Funktion:
def augmented_assignment_sum(iterable, start=0):
for n in iterable:
start += n
return start
?
Obwohl sum(ITERABLE)
es sehr elegant ist, wird +
stattdessen der Operator verwendet +=
, was bei np.ndarray
Objekten die Leistung beeinträchtigen kann.
Ich habe getestet, dass meine Funktion möglicherweise so schnell ist wie sum()
(während die entsprechende Verwendung +
viel langsamer ist). Da es sich um eine reine Python-Funktion handelt, ist ihre Leistung vermutlich immer noch beeinträchtigt, daher suche ich nach einer Alternative:
In [49]: ARRAYS = [np.random.random((1000000)) for _ in range(100)]
In [50]: def not_augmented_assignment_sum(iterable, start=0):
...: for n in iterable:
...: start = start + n
...: return start
...:
In [51]: %timeit not_augmented_assignment_sum(ARRAYS)
63.6 ms ± 8.88 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [52]: %timeit sum(ARRAYS)
31.2 ms ± 2.18 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [53]: %timeit augmented_assignment_sum(ARRAYS)
31.2 ms ± 4.73 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [54]: %timeit not_augmented_assignment_sum(ARRAYS)
62.5 ms ± 12.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [55]: %timeit sum(ARRAYS)
37 ms ± 9.51 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [56]: %timeit augmented_assignment_sum(ARRAYS)
27.7 ms ± 2.53 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Ich habe versucht, in functools.reduce
Kombination mit zu verwenden operator.iadd
, aber die Leistung ist ähnlich:
In [79]: %timeit reduce(iadd, ARRAYS, 0)
33.4 ms ± 11.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [80]: %timeit reduce(iadd, ARRAYS, 0)
29.4 ms ± 2.31 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Ich interessiere mich auch für Speichereffizienz und bevorzuge daher erweiterte Zuweisungen, da keine Zwischenobjekte erstellt werden müssen.
np.add.reduce(ARRAYS)
?374 ms ± 83.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
:-( Obwohl es erheblich schneller ist, wennARRAYS
2D-Array ist.axis=0
. Dann dauert es355 ms ± 16.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
:-( Intern verwendet esnp.add.reduce()
(numpy v. 1.15.4)np.dot(your_array, np.ones(len(your_array)))
. Sollte zu BLAS wechseln und relativ schnell sein.Antworten:
Die Antwort auf die Überschriftenfrage --- Ich hoffe, @Martijn Pieters wird meine Wahl der Metapher verzeihen --- direkt aus dem Maul des Pferdes lautet: Nein, es gibt keine solche eingebaute.
Wenn wir ein paar Codezeilen zulassen, um ein solches Äquivalent zu implementieren, erhalten wir ein ziemlich kompliziertes Bild mit dem, was je nach Operandengröße am schnellsten ist:
Diese Grafik zeigt die Zeitabläufe verschiedener Methoden in Bezug auf
sum
die Größe der Überoperanden. Die Anzahl der Terme beträgt immer 100. Diesaugmented_assignment_sum
zahlt sich für relativ große Operandengrößen aus. Die Verwendungscipy.linalg.blas.*axpy
sieht über den größten Teil des getesteten Bereichs ziemlich wettbewerbsfähig aus, wobei der Hauptnachteil darin besteht, dass sie weniger einfach zu bedienen ist alssum
.Code:
quelle