2017-12-12 7 views
3

ゴール: 私は、多くの重複した距離の大きな1d配列(3000000+)の距離を持っています。私は配列にn回現れるすべての距離を返す最も速い関数を書くことを試みています。私はnumpyで関数を書いていますが、コードの1行にボトルネックがあります。 2400の異なる大規模配列のforループで計算が行われるため、迅速なパフォーマンスが問題となります。Python/Numpyはすでに大きな配列のための最も速いコードを書いていますか?

import numpy as np 
for t in range(0, 2400): 
a=np.random.randint(1000000000, 5000000000, 3000000) 
b=np.bincount(a,minlength=np.size(a)) 
c=np.where(b == 3)[0] #SLOW STATEMENT/BOTTLENECK 
return c 

期待される結果: [2000000000,3005670000,2000000000,12345667,4000789000,12345687,12345667,2000000000,12345667] Iバックの配列を予想距離の1Dアレイを考えます[ 2000000000,12345667]を照会すると、メイン配列に3回現れるすべての距離の配列が返されます。

どうすればよいですか?

+1

あなたがちょうどあなたができるだけ速く欲しいものを買ってあげるセットにリスト全体を変換する場合はかなり確信して。 [This](https://stackoverflow.com/a/12897477/3715522)は良い指針を与えるはずです。 – MCBama

+2

リストをセットに変換することはまったく機能しません。それは重複を取り除き、N回出現するものを数えないようにします。 –

+0

Ah。私はその質問を誤解した。 – MCBama

答えて

3

使用np.unique

a=np.random.randint(0,10**6,3*10**6) 
uniques,counts=np.unique(a,return_counts=True) 
In [293]: uniques[counts==14] 
Out[293]: array([ 4541, 250510, 622471, 665409, 881697, 920586]) 

これは秒未満かかります。私はあなたのwhereステートメントが遅い理由を理解していません。私にとってあなたのソリューションは、より高速である:

In [313]: %timeit b=np.bincount(a,minlength=a.size) 
61.5 ms ± 4.82 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) 

In [314]: %timeit np.where(b==3)[0] 
11.8 ms ± 271 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 

In [315]: %timeit uniques,counts=np.unique(a,return_counts=True) 
424 ms ± 6.82 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

In [316]: %timeit Counter(a) 
1.41 s ± 18 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

EDIT

@numba.jit() 
def count(a,n): 
    counters=np.zeros(10**6,np.int32) 
    for i in a: 
     counters[i] += 1 
    res=np.empty_like(counters) 
    k = 0  
    for i,j in enumerate(counters): 
     if j == n: 
      res[k] = i 
      k += 1 
    return res[:k]   

このnumba機能を使用すると、3倍の改善を与えることができます。より多くの場合、並列ソリューション、on GPU for exampleを見つける必要があります。

In [26]: %timeit count(a,13) 
23.6 ms ± 1.56 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) 
+0

はい!私のソリューションはユニークなものよりも高速ですが、私はあなたのソリューションを実行しましたが、2400ループの大規模なデータセットに入れたときに、ソリューションの合計時間は3分で数秒です。私は2400回のループを3分から20-30秒以内にすることを望んでいた – user3152377

+1

@ user3152377すべての公正で、あなたはたくさんの番号で作業しています。コンピュータは高速ですが、ここで費やす時間を実際に短縮する唯一の方法は、より高速なものを得ることです。私がnumpyがあなたのコードを使っていて、時間がかかっているとすれば、その物を効率的にするのはかなり良い仕事だと思っています。まあ...はるかに優れた解決策が見つかるかどうかは分かりません。 – MCBama

+0

正直な答えをありがとう。私の特定のケースで心配する必要があるか、単にプロセッサのスピードとコアの量を心配する必要があるかどうかは分かりますか?今私は16GBのRAMを搭載したラップトップ(Mac)でこれをやっています---それ以上のRAMが必要な場合は、ラップトップは動作しません。また、Linuxは、Macよりもpythonのようなもののほうがはるかに速いと聞いています...聞いたことがありますか? – user3152377

1

あなたはCounterを使用することができます。

>>> a = np.array([2000000000,3005670000,2000000000,12345667,4000789000,12345687,12345667,2000000000,12345667]) 
>>> c = Counter(a) 
>>> np.array([i for i in c if c[i] >= 3]) 
array([2000000000, 12345667]) 
+0

はい!これはもう一つの素早いものですが、2400ループに置くと約3-4分の時間とほぼ同じ時間がかかりますが、2400ループの合計時間が30秒未満の解決策を望んでいました。 – user3152377

関連する問題