2016-03-21 12 views
1

私は現在、Python辞書を使用しているときにパフォーマンスの問題を抱えています。私はいくつかの巨大なdicts(最大30kのエントリ)を持っている、と私はこれらのエントリの相互比較を行いたい。したがって、1つのエントリ(識別子がキー)が与えられた場合、このキーでこのエントリを含む他のディクテーションもいくつですか?現在、私のマシンでは最大5時間かかりますが、私のツールには数分で動作するはずです。私はすでに検索をより効率的にするためにエントリーを削除しようとしました。Python辞書の相互比較が遅すぎる、改善?

all_cached_dataは、これらのdictsのリストを持つリストです。 sourcesには、all_cached_dataのリストに関する情報のリストがあります。

appearsin_list = [] 

# first, get all the cached data 
sources = sp.get_sources() 
all_cachedata = [0]*len(sources) 
for source in sources: 
    iscached = source[8] 
    sourceid = int(source[0]) 
    if iscached == "True": 
     cachedata, _ = get_local_storage_info(sourceid) 
    else: 
     cachedata = [] 
    all_cachedata[sourceid-1] = cachedata 

# second, compare cache entries 
# iterate over all cached sources 
for source in sources: 
    sourceid = int(source[0]) 
    datatype = source[3] 
    iscached = source[8] 
    if verbose: 
     print("Started comparing entries from source " + str(sourceid) + 
       " with " + str(len(all_cachedata[sourceid-1])) + " entries.") 

    if iscached == "True": 
     # iterate over all other cache entries 
     for entry in all_cachedata[sourceid-1]: 
      # print("Comparing source " + str(sourceid) + " with source " + str(cmpsourceid) + ".") 
      appearsin = 0 
      for cmpsource in sources: 
       cmpsourceid = int(cmpsource[0]) 
       cmpiscached = cmpsource[8] 
       # find entries for same potential threat 
       if cmpiscached == "True" and len(all_cachedata[cmpsourceid-1]) > 0 and cmpsourceid != sourceid: 
         for cmpentry in all_cachedata[cmpsourceid-1]: 
          if datatype in cmpentry: 
           if entry[datatype] == cmpentry[datatype]: 
            appearsin += 1 
            all_cachedata[cmpsourceid-1].remove(cmpentry) 
            break 

      appearsin_list.append(appearsin) 
      if appearsin > 0: 
       if verbose: 
        print(entry[datatype] + " appears also in " + str(appearsin) + " more source/s.") 
      all_cachedata[sourceid-1].remove(entry) 

avg = float(sum(appearsin_list))/float(len(appearsin_list)) 

print ("Average appearance: " + str(avg)) 
print ("Median: " + str(numpy.median(numpy.array(appearsin_list)))) 
print ("Minimum: " + str(min(appearsin_list))) 
print ("Maximum: " + str(max(appearsin_list))) 

これをスピードアップするためのヒントについては、非常に感謝しています。

+0

あなたはスクリプト言語で四重にネストされたループが30Kを扱うための良い方法だと思うどのような可能性が作られましたのデータですか? –

+0

これはまさに私の問題です。私は悲しいことに、これは良いアプローチではないことを知っています。しかし、行列多項式として、これはそのままであるように思えます。高速ではなく、実際にはアルゴリズム的な方法では、増やすことはできません。だから私はそれに対処しなければならないし、もっと速いものがあるかもしれない。私はすでにnumpyについて考えましたが、私のデータをnumpy配列にマップする方法はわかりません。 – Lawlrenz

+0

アルゴリズムを修正する必要があります。コードのどの部分が重要であり、どの部分が重要でないかは明確ではありません。 'cmpsource [8]'です。すべての用語を説明するのではなく、いくつかの単純なデータを使って、あなたが望むだけの仕組み、つまり比較と削除といういくつかの新しいコードを書いてください。 [mcve]の作成方法を参照してください。 –

答えて

0

あなたのアルゴリズムは改善できると思います。この場合ネストされたループは大きくありません。私はまた、Pythonがおそらくこの特定のpurpouseのための最高ではないと思う:大量のデータの比較と検索を行うためにSQLを使用する。 sqlite_objectのようなものを使用して、SQLiteデータベースのデータセットを変換して照会することができます。 純粋なPythonを使いたい場合は、Cythonでスクリプトをコンパイルしようとすることができます。あなたはスピードのいくつかの共振可能な改善を持つことができます。

http://docs.cython.org/src/tutorial/pure.html

次に、あなたは、いくつかの静的タイプヒンティングを使用してコードを向上させることができます

http://docs.cython.org/src/tutorial/pure.html#static-typing

+0

ありがとうございました。この場合、SQLを使用することは可能ですが、真剣にそれについて考えることはありませんでした。より速くなければなりません。 – Lawlrenz

関連する問題