2016-04-30 12 views
1

私は2つの3次元numpy配列A、B(size〜(1000,1000,3) - >画像処理)とそれに対する要素的な関数を持っています。numpy関数の時間効率の良い組み合わせ

機能は順次、次のとおりです。

import numpy as np 
A = A ** 3 
A = np.maximum(A, 0.001) 
C = np.divide(B, A) 

これらの3つのコマンドを操作する機能は、時間の厳しいプロセスのボトルネックとなっているので、私はとのそれらのすべてを実行する方法があるかどうかをお尋ねしたいと思いますメモリ内の各要素への単一アクセス、すなわち最も速い性能。

私が見出すことのできる唯一の組み合わせは、分割部分です。 hereまたはhere、またはthis oneです。これは、アインシュタイン合計のために特別なケースです。

カスタムufuncを書く必要なく、メモリの各要素に一度アクセスする(時間効率が良い)方法はありますか?

+0

3番目のリンクを使用するデータ型では、 'A *** 3'をシミュレートするために' np.einsum( 'ijk、ijk、ijk-> ijk'、A、A、A)を実行できますか?それは本当に効率的なはずです。 – Divakar

答えて

3

カスタムufuncを書く必要なく、メモリ内の各要素に1回アクセスする(時間効率が良い)方法はありますか?

はい、これはまさにnumexprのためのものです。

import numpy as np 
import numexpr as ne 

def func1(A, B): 
    A = A ** 3 
    A = np.maximum(A, 0.001) 
    return np.divide(B, A) 

def func2(A, B): 
    return ne.evaluate("B/where(A**3 > 0.001, A**3, 0.001)", 
         local_dict={'A':A,'B':B}) 

A, B = np.random.randn(2, 1000, 1000, 3) 

print(np.allclose(func1(A, B), func2(A, B))) 
# True 

numexprあなたの元のコードの上に70倍の改善について示します:

In [1]: %%timeit A, B = np.random.randn(2, 1000, 1000, 3) 
func1(A, B) 
    ....: 
1 loop, best of 3: 837 ms per loop 

In [2]: %%timeit A, B = np.random.randn(2, 1000, 1000, 3) 
func2(A, B) 
    ....: 
The slowest run took 8.87 times longer than the fastest. This could mean that an 
intermediate result is being cached. 
100 loops, best of 3: 11.5 ms per loop 

一部でnumexprが、それはそれでも、単一のスレッドで、デフォルトでは計算のために複数のスレッドを使用するためでありますまだ素朴なベクトル化を押しつぶす:

In [3]: ne.set_num_threads(1) 
Out[3]: 8 

In [4]: %%timeit A, B = np.random.randn(2, 1000, 1000, 3) 
func2(A, B) 
    ....: 
10 loops, best of 3: 47.3 ms per loop 
+0

そのスピードアップは巨大です!私の最後に似たような数字を確認しました。 – Divakar

+0

確かに印象的です。ありがとう! – GrigorisG

2

率直に言って、numexprはワンライナーに​​記載されていますは、関連するスピードアップ番号があれば、行く方法のように見えます。この記事に掲載されているNumPyの情報は、の代替候補です。

レッツ・時間これらの命令を1つずつ任意のボトルネックがあるかどう見る -

In [108]: # Random input arrays 
    ...: A = np.random.rand(1000,1000,3) 
    ...: B = np.random.rand(1000,1000,3) 
    ...: 

In [109]: %timeit A**3 
1 loops, best of 3: 442 ms per loop 

In [110]: A = A ** 3 

In [111]: %timeit np.maximum(A, 0.001) 
100 loops, best of 3: 16.4 ms per loop 

In [112]: A = np.maximum(A, 0.001) 

In [113]: %timeit np.divide(B, A) 
10 loops, best of 3: 19.7 ms per loop 

だから、それは電力計算が総実行時間の巨大な部分を占めているようです。

np.einsumを紹介しますが、関連するデータ型に注意してください。

In [114]: # Random input arrays 
    ...: A = np.random.rand(1000,1000,3) 
    ...: B = np.random.rand(1000,1000,3) 
    ...: 

In [115]: %timeit A**3 
1 loops, best of 3: 442 ms per loop 

In [116]: %timeit np.einsum('ijk,ijk,ijk->ijk',A,A,A) 
10 loops, best of 3: 28.3 ms per loop 

In [117]: np.allclose(A**3,np.einsum('ijk,ijk,ijk->ijk',A,A,A)) 
Out[117]: True 

これは優れたスピードアップです。

関連する問題