2016-12-13 3 views
2

Ist das ein Cache-Ding, wie Timeit es vorschlägt?In NumPy werden größere Arrays schneller erstellt?

In [55]: timeit a = zeros((10000, 400)) 
100 loops, best of 3: 3.11 ms per loop 

In [56]: timeit a = zeros((10000, 500)) 
The slowest run took 13.43 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 3.43 µs per loop 

versucht, es zu täuschen, aber es hat nicht funktioniert:

In [58]: timeit a = zeros((10000, 500+random.randint(100))) 
The slowest run took 13.31 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 4.35 µs per loop 
+0

vielleicht zeitlich ich 100000 Schleifen, am besten von 3: 4,57 & mgr; s pro Schleife 100000 Schleifen, am besten von 3: 4,64 & mgr; s pro Schleife Wenn Sie Ihren Code laufen lassen, ist der Unterschied minimal – EdChum

+0

Versuchen Sie 'Ones' stattdessen. Oder füge ein 'fill' hinzu. – hpaulj

+0

Dies ist auf meinem Rechner ziemlich konsistent. die Verwendung von "Einsen" ist langsam (3-4ms) in beiden Größen. – Bach

Antwort

2

Der Grund Caching ist nicht, aber das numpy erzeugt nur einen Platzhalter anstelle des vollständigen Arrays. Dies kann leicht durch die Überwachung Ihrer RAM-Nutzung überprüft werden, wenn Sie so etwas tun:

a = np.zeros((20000, 20000), np.float64) 

Dies gilt zuteilen nicht 20k * 20k * 8Byte ~ 3GB auf meinem Computer (aber möglicherweise OS-abhängig, da np.zeros verwendet die C-Funktion calloc). Aber seien Sie vorsichtig, weil die meisten Operationen auf diesem Array (zum Beispiel a += 5) diesen Speicher sofort zuweisen! Stellen Sie sicher, dass Sie eine angemessene Größe im Vergleich zu Ihrem RAM verwenden, so dass Sie bemerken, dass der RAM zunimmt, ohne ihn zu überlasten.

Am Ende verschiebt dies nur die Zuweisung des Arrays, sobald Sie damit arbeiten, sollte das kombinierte Timing von Zuweisung und Betrieb wie erwartet sein (linear mit der Anzahl der Elemente). Es scheint, Sie IPython verwenden, so dass Sie eine Block-timeit %%timeit verwenden:

%%timeit 
a = np.zeros((10000, 400)) 
a += 10 
# => 10 loops, best of 3: 30.3 ms per loop 

%%timeit 
a = np.zeros((10000, 800)) 
a += 10 
# => 10 loops, best of 3: 60.2 ms per loop 
+0

Großartige Erklärung !! Das scheint es tatsächlich zu sein. – Bach

+0

Beachten Sie, dass dieser Platzhalter tatsächlich sehr gut sein kann. Wenn ich nach dem Erstellen eines riesigen Arrays (sagen wir mal) nur ein [0,0] berühre, dann kostet es überhaupt keine Zeit (und reserviert keinen Speicher für den Rest des Arrays). Ich frage mich, ob der Größenschwellenwert innerhalb von Python konfigurierbar ist. – Bach

+0

Ich habe versucht, den Schwellenwert im numpigen Quellcode zu finden, habe ihn aber nicht gefunden. Beachten Sie, dass es sogar "Calloc" sein könnte, was diese Optimierung macht. Wie auch immer, es wird höchstwahrscheinlich in einer 'C' Datei sein, also keine Möglichkeit, es einfach innerhalb von Python zu ändern. – MSeifert