2016-04-25 10 views
6

Dizilemez sayıları (çok sayıda gigabayt) işaretsiz 32 bitlik girişleri depolamak için dizi modüllerini kullanıyorum. Her öğe için 4 bayt kullanmak yerine, python array.itemsize ile belirtildiği gibi 8 bayt kullanır ve pympler tarafından doğrulanır.Python dizi öğelerini belirli bir boyuta sahip olmaya zorlayabilir miyim?

örn

>>> array("L", range(10)).itemsize 
8 

I elemanları çok sayıda olması, bu yüzden 4 bayt içinde depolayarak yararlı olacaktır.

Numpy beni işaretsiz 32 bit ints gibi değerleri depolamak sağlayacak

:

>>> np.array(range(10), dtype = np.uint32).itemsize 
4 

Ama sorun numpy dizin operatörü kullanılarak herhangi bir operasyon olması yaklaşık iki kat daha yavaş, vektör işlemleri olmayan işlemler desteklenen bu yüzden tarafından numpy yavaştır. örn:

python3 -m timeit -s "from array import array; a = array('L', range(1000))" "for i in range(len(a)): a[i]" 
10000 loops, best of 3: 51.4 usec per loop 

yüzden zorundayım

python3 -m timeit -s "import numpy as np; a = np.array(range(1000), dtype = np.uint32)" "for i in range(len(a)): a[i]" 
10000 loops, best of 3: 90.4 usec per loop 

vs ya ben istiyorum veya program istediğim iki kat yavaş çalışacağını iki katı kadar bellek kullanır. Bunun etrafında bir yolu var mı? Python dizilerini belirtilen itemsize kullanmaya zorlayabilir miyim?

+0

https://bugs.python.org/issue26821 –

+0

Bu yanlış bir ikilemdir: programınız daha az bellek kullanabilir ve daha hızlı olabilir. Farklı platformlarda sabit boyutlu 'dizi 'öğeleri kullanıp kullanamayacağınız sorusuyla ilgisi olmamasına rağmen (' dizi' muhtemelen platforma özgü C tipi boyutları kullanır). Ayrı bir sorudur: belirli numpy tabanlı hesaplamaları daha hızlı nasıl yapılır. – jfs

cevap

5

sen sopa istiyorsanız array kullanarak, set the typecode

>>> array.array("I", range(10)).itemsize 
4 
: I ( unsigned int) yerine L ( unsigned long) için

Yani, hesaplamanızı hızlandırmanın 2x'ten daha fazla hızlandırmanın bir yolu olmasaydı çok şaşırırdım. Bu değerlerle ne yaptığınızı tam olarak bilmeden söylemek zor.

1

2 şey: numpy.arange() (iç yöntemi)

kullanmak ve (bilgisayar hız nedenleriyle) Numpy ile tablolar için kullanmaktan kaçının. Yayınlama tekniklerini mümkün olduğunca kullanmaya çalışın.

Tüm öğeleri almanın daha kolay bir yolu, numpy dizisinin şekli yoluna giriyorsa .ravel() öğesini kullanmaktır. 3 iyi

python3 -m timeit -s "import numpy as np; a = np.arange(1000), 
....... dtype = np.uint32)" "for i in range(len(a)): a[i]" 

10000 döngüler,: döngü başına 106 mikrosaniye

python3 -m timeit -s "import numpy as np; a = np.arange(1000), 
....... dtype = np.uint32)" "a.ravel()" 

1000000 döngüler, 3 iyi: döngü başına 0.218 mikrosaniye

1

here, array.array, özel bir ilgisi olmayan (bilgim için) eski bir araçtır.

Verimlilik sorunlarınız varsa, numpy.array, array.array'dan daha iyi bir seçimdir, çok sayıda optimize edilmiş vektör araçlarıyla sağlanır. Bu durumda, 32bit operasyonlar bile 64 bit sistemde, 64bits olanlardan daha çabuk olur:

Gördüğünüz gibi
import numpy as np 
In [528]: %timeit np.sum(a32) 
1000 loops, best of 3: 1.86 ms per loop 

In [529]: %timeit np.sum(a64) 
100 loops, best of 3: 2.22 ms per loop 

In [530]: %timeit sum(a32) 
1 loop, best of 3: 572 ms per loop 

In [531]: %timeit sum(a64) 
1 loop, best of 3: 604 ms per loop 

, sen yavaş saf piton döngüler, kaçınmak gerekir.