2016-04-01 19 views
9

Bir performans darboğaz var. Büyük dizilerin sütun-bilge ortalamasını (250 satır & 1,3 milyon sütun) hesaplıyorum ve uygulamada bir milyondan fazla kez yapıyorum. PythonYüksek performanslı dizi ortalama

Benim test durumu:

import numpy as np 
big_array = np.random.random((250, 1300000)) 
%timeit mean = big_array.mean(axis = 0) # ~400 milliseconds 

Numpy tek çekirdek üzerinde çalışan, benim makinede yaklaşık 400 milisaniye sürer. Farklı dillerden (Cython, R, Julia, Torch) farklı matrix kütüphaneleri denedim, ancak sadece Julia'yı Numpy'yi yenmek için 250 milisaniyeye ulaşarak buldum.

Bu görevde performansta önemli gelişmeler olduğuna dair herhangi bir kanıt var mı? Belki bu GPU için uygun bir görev midir?

Düzenleme: Uygulamam hafızada kısıtlı ve performansı, büyük bir dizinin öğelerine tekrar tekrar değil, yalnızca bir kez erişerek önemli ölçüde geliştirildi. (Aşağıya bakınız.)

+1

Bu hesaplama, büyük olasılıkla CPU işleminden ziyade bellek erişimi hakkında daha fazladır. Burada herhangi bir sistemin önemli ölçüde geliştirilmesini beklemezdim. Sezgim, çoklu çekirdek veya GPU kullanmanın çok fazla kullanılmayacağıydı. Şamandıraya düşürülmesi32 yardımcı olabilir. – MRocklin

+0

Test durumu çok basit olabilir. Dizi türüm aslında boolean olacak, bu yüzden her öğe Numpy ile bir bayt olarak saklanır. Paradoksal olarak, örnek olarak floatlardan ziyade boole dizisi için ortalama veya toplamı almak daha uzun sürer. Bellek trafiğini ~% 90 azaltacak olan bitpacked dizisinde nasıl işlem yapılacağı hakkında bir fikriniz var mı? –

+0

Benim özel uygulamasında, 22.000 satırlık dizinin 250 satırlık alt kümeleri olan dizilerin ortalamasını aldım. Bellek tüm hesaplama için tek başına toplam 24+ saate erişir. Bununla birlikte, daha büyük matris üzerinde çalışır ve her bir öğeye yalnızca bir kez dokunursak, bellek toplam 10 saniyeden daha azına erişir. Bunu denemek zorundayım! Darboğaz işaret için teşekkürler @MRocklin. –

cevap

9

Julia, eğer yanılmıyorsam, varsayılan olarak C bellek düzenini kullanan numpy'in tersine bellekte fortran düzenini kullanır. Eğer ortalama ardışık bellek boyunca oluyor böylece aynı düzene uymaları şeyleri yeniden düzenlemek Yani, daha iyi performans elde:

In [1]: import numpy as np 

In [2]: big_array = np.random.random((250, 1300000)) 

In [4]: big_array_f = np.asfortranarray(big_array) 

In [5]: %timeit mean = big_array.mean(axis = 0) 
1 loop, best of 3: 319 ms per loop 

In [6]: %timeit mean = big_array_f.mean(axis = 0) 
1 loop, best of 3: 205 ms per loop 

Ya da sadece size boyutlarını değiştirmek ve diğer eksen üzerinde ortalama alabilir:

In [10]: big_array = np.random.random((1300000, 250)) 

In [11]: %timeit mean = big_array.mean(axis = 1) 
1 loop, best of 3: 205 ms per loop 
+0

Bilgisayarımda zamanlama tersine çevriliyor: [56] içinde:% timeit big_array.mean (0) -> loop başına 705 ms; [57] 'de: döngü başına% timeit big_arrayf.mean (0) -> 1201 ms; Bir fikrin var mı? –

İlgili konular