計算時間に関する質問になります.
Pop count (2進数表記におけるbitが1であるものの個数) を求める関数popcountと, 同様のことが可能な組み込み関数count('1')の実行時間をそれぞれ出力し, さらにその結果をpythonとPyPyで比較します.
Python
1def popcount(n): 2 c = (n & 0x5555555555555555) + ((n >> 1) & 0x5555555555555555) 3 c = (c & 0x3333333333333333) + ((c >> 2) & 0x3333333333333333) 4 c = (c & 0x0f0f0f0f0f0f0f0f) + ((c >> 4) & 0x0f0f0f0f0f0f0f0f) 5 c = (c & 0x00ff00ff00ff00ff) + ((c >> 8) & 0x00ff00ff00ff00ff) 6 c = (c & 0x0000ffff0000ffff) + ((c >> 16) & 0x0000ffff0000ffff) 7 c = (c & 0x00000000ffffffff) + ((c >> 32) & 0x00000000ffffffff) 8 return c
検証方法としては, 恣意的に選んだ64bit以下の大きな数Nのpopcountを 30 ** 2 回計算し, 全体の時間を求めるということを行っております.
Python
1import time 2 3N = 2 ** 63 + 5 ** 15 4s = time.perf_counter() 5 6for _ in range(3000): 7 for _ in range(3000): 8 a = popcount(N) 9 10t = time.perf_counter() 11print(t - s) 12 13s = time.perf_counter() 14 15for _ in range(3000): 16 for _ in range(3000): 17 a = bin(N).count('1') 18 19t = time.perf_counter() 20print(t - s)
これをpython3.9で実行すると
popcount関数→ 6.4915954秒
組み込み関数→ 3.3203775秒
という結果になり, またPyPy3.11で行ったときには
popcount関数→ 0.0214806秒
組み込み関数→ 1.3355724秒
という結果が得られました.
ここでご教授いただきたい質問とは, PyPy において popcount 関数が高速であることは分かったが, pythonでそれを行った場合に組み込み関数より遅くなってしまうのはどうしてか, ということです.
このpopcount関数はそれを求めるのに高速なアルゴリズムとして紹介されていた関数です.
一般に速いということは理解しております.
そうであるのにpythonで動作させると非常に遅くなってしまうのはなぜなのでしょうか.
count('1')の構造や, pythonとpypyの違い等について, 何かご存知の方がいらっしゃれば, この原因を推測していただきたいです.
拙い知識と説明になりますが, 何卒宜しくお願い致します.
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/07/29 13:19
2022/07/29 13:47
2022/07/30 04:24