私は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 data
とdel locate
の間にallin
timeit
コールの間)?私はちょうど私が間違ってスワップで動作するようにnumpyメソッドを強制していないので、本当に遅くなることを確実にしたいです。
(読み込み時にnumpyの配列が約60MBになるので、一度読み込むとスワップには入りませんが、何度も読み込まれるとスワップに入ることがあります)。
暗黙的にクリアされるわけではありませんが、ソースコード内のものから、 'timeit'に渡されるものは本質的にループで実行されるため、暗黙的に取得される各反復で同じ変数が使用されます私は思う古いデータを取り除いています(ただし、文が実行される前または後にメモリがクリアされているかどうかはわかりませんが)。 – Andrew
は、最後のコメントをより明確にするために、基本的に私たちが(擬似コードで)得るのは 'timer.start:for _ in range(number):x = np.genfrom ...:timer.stop'です。私は、 'genfromtxt'が呼び出されたときにメモリを上書きし続けるべきだと考えています。したがって、変数の再割り当てがどうなっているのか分からない限り、手動で' data'変数をクリアする必要はありません。 – Andrew
@Andrew、変数が再割り当てされたときにオブジェクトがガベージコレクションされるはずです(オブジェクトへの他の参照がないと仮定します)。オブジェクト2が割り当てられるまで、object1はガベージコレクションされないため、ピーク時に2倍のメモリ使用量を持ちます。 –