2016-08-17 29 views
0

私はPythonで作業しようとしている、適度なサイズのソートされたアスキーテキストファイルを持っています。私は時間の関数を使用して書いた単純なバイナリ検索関数を使うのではなく、ファイル全体をメモリに読み込み、検索するためにnumpyの論理インデックスを使用する方が検索の回数を決めることを試みています。これを行うために、私は次のセットアップ各繰り返しの後でローカルメモリをクリアしますか

私はそれがそれぞれのタスクを完了するのにかかる時間の平均量を比較する timeitを使用しています
import os 
import timeit 
import numpy as np 


def binsearch(file, label, col=0, start=0, stop=None, linelength=None): 

    if linelength is None: 
     file.seek(0, os.SEEK_SET) 
     file.readline() 
     linelength = file.tell() 

    if stop is None: 
     file.seek(0, os.SEEK_END) 
     stop = file.tell() 

    stopline = stop // linelength 
    startline = start // linelength 

    midline = (stopline-startline) // 2 + startline 

    mid = midline*linelength 

    file.seek(mid, os.SEEK_SET) 

    line = file.readline() 

    if not line: 
     return None 

    linelab = int(line.split()[col]) 

    if linelab == label: 
     return line 
    elif midline == startline or midline == stopline: 
     return None 
    elif linelab < label: 
     start = mid 
     return binsearch(file, label, col=col, start=start, stop=stop, linelength=linelength) 
    elif linelab > label: 
     stop = mid 
     return binsearch(file, label, col=col, start=start, stop=stop, linelength=linelength) 


filepath = '/Users/aliounis/UCAC4/u4i/u4xtycho' 
data0 = np.genfromtxt(filepath, dtype=np.int, names=['tycid', 'ucacid', 'rnm']) 
numsearch = 10000 
checks = data0['ucacid'][np.random.randint(0, 259788-1, numsearch)] 
del data0 

allin = """ 
data = np.genfromtxt(filepath, dtype=np.int, names=['tycid', 'ucacid', 'rnm']) 

locate = checks.reshape(1, -1) == data['ucacid'].reshape(-1, 1) 

print(data[np.any(locate, axis=1)].shape) 
""" 

bins = """ 
file = open(filepath, 'r') 
recs = [] 
dtypes = np.dtype([('tycid', np.int), ('ucacid', np.int), ('rnm', np.int)]) 
for val in checks: 
    line = binsearch(file, val, col=1) 
    if line is not None: 
     recs.append(np.array([tuple(np.fromstring(line, dtype=np.int, sep=' '))], dtype=dtypes)) 

print(np.concatenate(recs, axis=0).shape) 
file.close() 
""" 
numattempts = 10 
print(timeit.timeit(allin, number=numattempts, globals=globals())/numattempts) 
print(timeit.timeit(bins, number=numattempts, globals=globals())/numattempts) 

を持っています。私はこれが公平なテストであるかどうか、特にnumpyの実装について知りたい。各実行の間にローカルメモリをクリアするかどうかを指定します(つまり、実行番号の間にdel datadel locateの間にallintimeitコールの間)?私はちょうど私が間違ってスワップで動作するようにnumpyメソッドを強制していないので、本当に遅くなることを確実にしたいです。

(読み込み時にnumpyの配列が約60MBになるので、一度読み込むとスワップには入りませんが、何度も読み込まれるとスワップに入ることがあります)。

答えて

0

はtimeitは、それはそれが何をするか見るために非常に簡単です通常のPythonで実装されているので:https://hg.python.org/cpython/file/2.7/Lib/timeit.py

けれども質問に答えるためにそれが文の一部またはセットアップ方法ではないのですから、いや、それはdel dataを実行しませんあなたは時間を過ぎています。その動作を望む場合は、setupメソッドとして追加する必要があります。

この場合、timeitがデフォルトでガベージコレクタを無効にして以来、毎回新しいメモリブロックになる同じ値に再割り当てします。

+0

暗黙的にクリアされるわけではありませんが、ソースコード内のものから、 'timeit'に渡されるものは本質的にループで実行されるため、暗黙的に取得される各反復で同じ変数が使用されます私は思う古いデータを取り除いています(ただし、文が実行される前または後にメモリがクリアされているかどうかはわかりませんが)。 – Andrew

+0

は、最後のコメントをより明確にするために、基本的に私たちが(擬似コードで)得るのは 'timer.start:for _ in range(number):x = np.genfrom ...:timer.stop'です。私は、 'genfromtxt'が呼び出されたときにメモリを上書きし続けるべきだと考えています。したがって、変数の再割り当てがどうなっているのか分からない限り、手動で' data'変数をクリアする必要はありません。 – Andrew

+0

@Andrew、変数が再割り当てされたときにオブジェクトがガベージコレクションされるはずです(オブジェクトへの他の参照がないと仮定します)。オブジェクト2が割り当てられるまで、object1はガベージコレクションされないため、ピーク時に2倍のメモリ使用量を持ちます。 –

関連する問題