基本事項
両方の文字列が1の場合のカウント方法は非常に遅いです。ここでは簡単な例を示します。
In [24]: a = '1010' * 2500
In [25]: b = '1100' * 2500
In [27]: def test1():
counter = 0
for i in range(len(a)):
if int(a[i]) == int(b[i]) == 1:
counter += 1
return counter
In [28]: %timeit test1()
100 loops, best of 3: 4.07 ms per loop
は、1と0のと同じくらいのビットのあなたの文字列を表して何かを使用することの比較:2045倍高速である
In [29]: aba = bitarray(a)
In [30]: bba = bitarray(b)
In [31]: def test2():
....: return (aba & bba).count()
....:
In [32]: %timeit test2()
100000 loops, best of 3: 1.99 µs per loop
。だから問題は、Pythonをスピードアップする方法ではなく、 "私はどのようなデータ構造を使うべきか"ということです。
In [22]: from bitarray import bitarray
In [23]: testdata = open('teststrs.txt')
In [24]: l = [bitarray(line.rstrip()) for line in testdata]
In [25]: len(l)
Out[25]: 10000
In [26]: len(l[0])
Out[26]: 100
In [27]: combs = combinations(l, 2)
In [28]: %time res = [(a & b[:len(a)]).count() for a, b in combs]
CPU times: user 1min 14s, sys: 396 ms, total: 1min 15s
Wall time: 1min 15s
か、あなたの例のコードのように、製品を使用して:bitarrayとあなたの最悪のケースではありません100の1の10,000行と0のファイル、ただしを使用して
大規模
:
In [30]: from itertools import product
In [31]: prod = product(l, repeat=2)
In [32]: %time res = [(a & b[:len(a)]).count() for a, b in prod]
CPU times: user 2min 51s, sys: 628 ms, total: 2min 52s
Wall time: 2min 51s
注:
あなたがそれを開いていないと、それはデッドコードが含まれているので、私は、あなたが持って取り扱い、結果をスキップ:直前にあなたがそのa < b
を確認した場合ので、
if a == b:
は、True
になることはありません。私はそれを正しく理解している場合、あなたの最悪のケースでは、データ
「実」
if a < b:
result = 0
elif a == b:
result = 1
else:
counter = 0
for i in range(len(l[a])):
if (int(l[a][i]) == int(l[b][i]) == 1):
counter += 1
result = counter/10000
print((a + 1), (b + 1), result)
:
In [1]: src = map(lambda i: '{:010000b}\n'.format(i), iter(lambda: random.getrandbits(10000), None))
In [2]: import random
In [3]: from itertools import islice
In [4]: with open('teststrs.txt', 'w') as datafile:
datafile.writelines(islice(src, 0, 4623))
...
In [35]: testdata = open('teststrs.txt')
In [36]: l = [bitarray(line.rstrip()) for line in testdata]
In [37]: prod = product(l, repeat=2)
In [38]: %time res = [(a & b).count() for a, b in prod]
CPU times: user 52.1 s, sys: 424 ms, total: 52.5 s
Wall time: 52.5 s
In [39]: len(l)
Out[39]: 4623
In [40]: len(l[0])
Out[40]: 10000
を私はあなたがインデントや論理エラーを持っていること、それを取ると、のようなものを意味し私は浮気してスライスをスキップしたことに注目してくださいb
。あなたの最大ビット幅が事前にわかっているのであれば
In [43]: %time res = [(a & b[:len(a)]).count() for a, b in prod]
CPU times: user 29min 40s, sys: 676 ms, total: 29min 41s
Wall time: 29min 40s
を、あるいはあなたのデータからそれを計算します。新しいコピーを作成して、スライスが行うであろう、周りのすべてのそのメモリを移動するために非常に非常にコストがかかります
In [18]: def test():
with open('teststrs.txt') as testdata:
lines = [line.strip() for line in testdata]
max_len = max(map(len, lines))
l = [bitarray(line.ljust(max_len, '0')) for line in lines]
prod = product(l, repeat=2)
return [(a & b).count() for a, b in prod]
....:
In [19]: %timeit test()
1 loops, best of 3: 43.9 s per loop
ここteststrsを:、私はそれがゼロで短いbitarraysパッドに有益であろうし、その後全体が「1のカウント」んだと思います。txtは、1と0の4623の混合長(ランダム選択100,1000または10000)の文字列で構成されていました。
コードが正しくインデントされていないように見えますが、修正できますか? – snakecharmerb
'if a
また、このコードが達成しようとしていることを説明した場合に役立ちます。サンプルコードをスピードアップするだけでは、他の最適化が可能かもしれません。 – snakecharmerb