2016-04-01 9 views
9

パフォーマンスのボトルネックがあります。私は大きな配列(250行& 130万列)の列方向平均を計算しています。私はそのアプリケーションで100万回以上を行います。高性能アレイの平均

Pythonで私のテストケース:

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

numpyのは、シングルコア上で実行されている、私のマシン上で約400ミリ秒かかります。私はさまざまな言語(Cython、R、Julia、Torch)でいくつかの他のマトリックスライブラリを試しましたが、JuliaだけがNumpyを打ち負かすのに約250ミリ秒かかっていました。

このタスクでは、パフォーマンスの大幅な向上の証拠は誰でも得ることができますか?おそらく、これはGPUに適したタスクですか?

編集:私のアプリケーションは明らかにメモリが制約されており、大規模な配列の要素に繰り返しアクセスするのではなく、1回だけアクセスすることでパフォーマンスが飛躍的に向上します。 (下のコメントを参照してください)

+1

この計算は、おそらくCPUの作業よりもメモリアクセスに関するものです。ここではnumpyを大幅に改善するシステムはないと思います。私の直感は、複数のコアやGPUを使うのはあまり役に立たないということです。 float32に減らすことは役に立ちます。 – MRocklin

+0

テストケースが単純すぎる可能性があります。私の配列型は実際にブール値になるので、すべての要素はNumpyのバイトとして格納されます。逆説的に、boolean配列の平均値や合計値は、例のように浮動小数点数に比べて長くなります。ビットパッキングされた配列の操作をどのように実行するか考えていますが、これはメモリトラフィックを90%削減しますか? –

+0

私の特定のアプリケーションでは、22,000行の配列の250行のサブセットである配列の平均をとっています。メモリアクセスだけで、計算全体で合計24時間以上になります。しかし、私が大きな行列で操作し、各要素を1回だけタッチすると、メモリアクセスは合計で10秒未満になります。私はそれを試さなければならない!ボトルネックを指摘してくれてありがとう@MRocklin。 –

答えて

9

私が間違っていないと、JuliaはデフォルトでCメモリレイアウトを使用するnumpyではなく、メモリ内でFortranの順序を使用します。あなたは平均が連続したメモリに沿って起こっているように、同じレイアウトに接着するように物事を並べ替えるのであれば、あなたはより良いパフォーマンスを得る:

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 

それとも、単にあなたの寸法を変更し、他の軸上の平均値を取ることができます。

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

私のコンピュータでは、タイミングが逆になります: [56]では、ループあたり%timeit big_array.mean(0) - > 705 ms; [57]:%timeit big_arrayf.mean(0) - >ループあたり1201ミリ秒。 ご存知ですか? –