Python3.11が高速化しているかベンチマークしてみた
こんにちは。CX事業本部Delivery部のakkyです。
2022年10月24日にPythonの最新版である3.11.0がリリースされました。 このリリースの目玉は実行速度の高速化です。
CPythonはいままで高速化にはあまり力を入れiませんでしたが、マイクロソフトの出資を受け、実行速度を4年間で5倍高速化するプロジェクトが始動しました。
Python3.11はその最初のリリースです。おおよそ1.2倍程度高速になっているとされていますが、実際のアプリケーションではどのような感じでしょうか? EC2で実験してみました。
検証環境
- Amazon EC2 M5zn.large 2vCPU 8GiB
- Ubuntu 22.04.1 LTS
- Python3.10.6(Ubuntu標準)
- Python3.11.0(deadsnakes:ppa使用)
- pyperformance(https://pyperformance.readthedocs.io/) 1.0.5
CPU情報
$ sudo lshw -class processor *-cpu description: CPU product: Intel(R) Xeon(R) Platinum 8252C CPU @ 3.80GHz vendor: Intel Corp. physical id: 4 bus info: cpu@0 version: 6.85.7 slot: CPU 0 size: 3800MHz width: 64 bits clock: 100MHz capabilities: lm fpu fpu_exception wp vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp x86-64 constant_tsc rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves ida arat pku ospke avx512_vnni configuration: cores=1 enabledcores=1 microcode=83898890 threads=2
フィボナッチ数を計算する関数
Python3.11では、関数の呼び出しが高速化されているとのことで、まずはフィボナッチ数を計算する関数で実験しました。
def fibonacci(n): if n == 0 or n == 1: return n else: return fibonacci(n - 2) + fibonacci(n - 1) import sys print(fibonacci(int(sys.argv[1])))
Python3.10.6
$ time python3.10 fibo.py 40 102334155 real 0m24.325s user 0m24.320s sys 0m0.004s
Python3.11.0
$ time python3.11 fibo.py 40 102334155 real 0m12.557s user 0m12.553s sys 0m0.004s
24秒から12秒と、2倍の実行速度が得られました!すごい!
pyperformance
実際のワークロードに近いベンチマークを提供するpyperformanceでも検証してみましょう。
※pipの関係でpyperformanceが3.10のsite-packagesに入りましたが、比較には影響ないかと思います。
$ python3.11 -m pyperformance compare py310.json py311.json py310.json ========== Performance version: 1.0.5 Report on Linux-5.15.0-1019-aws-x86_64-with-glibc2.35 Number of logical CPUs: 2 Start date: 2022-10-28 04:46:09.095860 End date: 2022-10-28 05:04:38.410011 py311.json ========== Performance version: 1.0.5 Report on Linux-5.15.0-1019-aws-x86_64-with-glibc2.35 Number of logical CPUs: 2 Start date: 2022-10-28 04:20:13.505432 End date: 2022-10-28 04:36:28.061482 ### 2to3 ### Mean +- std dev: 298 ms +- 3 ms -> 225 ms +- 5 ms: 1.32x faster Significant (t=96.12) ### chameleon ### Mean +- std dev: 7.63 ms +- 0.05 ms -> 5.49 ms +- 0.08 ms: 1.39x faster Significant (t=172.42) ### chaos ### Mean +- std dev: 89.1 ms +- 0.8 ms -> 52.9 ms +- 0.5 ms: 1.68x faster Significant (t=310.52) ### crypto_pyaes ### Mean +- std dev: 95.4 ms +- 0.7 ms -> 59.4 ms +- 0.7 ms: 1.61x faster Significant (t=268.86) ### deltablue ### Mean +- std dev: 6.26 ms +- 0.12 ms -> 3.18 ms +- 0.04 ms: 1.97x faster Significant (t=184.93) ### django_template ### Mean +- std dev: 38.6 ms +- 0.4 ms -> 26.9 ms +- 0.4 ms: 1.43x faster Significant (t=164.75) ### dulwich_log ### Mean +- std dev: 63.2 ms +- 0.5 ms -> 53.7 ms +- 0.3 ms: 1.18x faster Significant (t=122.83) ### fannkuch ### Mean +- std dev: 411 ms +- 5 ms -> 300 ms +- 2 ms: 1.37x faster Significant (t=152.91) ### float ### Mean +- std dev: 97.2 ms +- 1.3 ms -> 64.3 ms +- 1.1 ms: 1.51x faster Significant (t=146.12) ### genshi_text ### Mean +- std dev: 24.9 ms +- 0.2 ms -> 18.0 ms +- 0.2 ms: 1.38x faster Significant (t=185.05) ### genshi_xml ### Mean +- std dev: 52.4 ms +- 0.6 ms -> 42.4 ms +- 0.5 ms: 1.24x faster Significant (t=105.21) ### go ### Mean +- std dev: 195 ms +- 1 ms -> 113 ms +- 1 ms: 1.73x faster Significant (t=325.79) ### hexiom ### Mean +- std dev: 7.86 ms +- 0.06 ms -> 5.19 ms +- 0.04 ms: 1.52x faster Significant (t=274.95) ### html5lib ### Mean +- std dev: 71.2 ms +- 3.7 ms -> 52.7 ms +- 3.1 ms: 1.35x faster Significant (t=29.58) ### json_dumps ### Mean +- std dev: 11.1 ms +- 0.1 ms -> 10.0 ms +- 0.1 ms: 1.11x faster Significant (t=60.62) ### json_loads ### Mean +- std dev: 21.9 us +- 0.2 us -> 20.8 us +- 0.3 us: 1.06x faster Significant (t=24.16) ### logging_format ### Mean +- std dev: 7.59 us +- 0.08 us -> 5.69 us +- 0.06 us: 1.33x faster Significant (t=146.99) ### logging_silent ### Mean +- std dev: 152 ns +- 4 ns -> 83 ns +- 0 ns: 1.82x faster Significant (t=128.58) ### logging_simple ### Mean +- std dev: 6.95 us +- 0.08 us -> 5.21 us +- 0.06 us: 1.33x faster Significant (t=131.98) ### mako ### Mean +- std dev: 13.0 ms +- 0.2 ms -> 8.9 ms +- 0.1 ms: 1.47x faster Significant (t=154.67) ### meteor_contest ### Mean +- std dev: 96.8 ms +- 0.3 ms -> 84.6 ms +- 0.3 ms: 1.14x faster Significant (t=207.94) ### nbody ### Mean +- std dev: 117 ms +- 1 ms -> 73 ms +- 1 ms: 1.62x faster Significant (t=286.70) ### nqueens ### Mean +- std dev: 82.3 ms +- 0.6 ms -> 68.2 ms +- 0.7 ms: 1.21x faster Significant (t=122.65) ### pathlib ### Mean +- std dev: 17.4 ms +- 0.1 ms -> 15.8 ms +- 0.2 ms: 1.10x faster Significant (t=49.42) ### pickle ### Mean +- std dev: 8.92 us +- 0.07 us -> 8.06 us +- 0.07 us: 1.11x faster Significant (t=65.07) ### pickle_dict ### Mean +- std dev: 23.5 us +- 0.2 us -> 24.3 us +- 0.1 us: 1.03x slower Significant (t=-32.44) ### pickle_list ### Mean +- std dev: 2.97 us +- 0.04 us -> 3.31 us +- 0.03 us: 1.11x slower Significant (t=-56.69) ### pickle_pure_python ### Mean +- std dev: 369 us +- 5 us -> 237 us +- 1 us: 1.55x faster Significant (t=213.55) ### pidigits ### Mean +- std dev: 157 ms +- 0 ms -> 156 ms +- 0 ms: 1.01x faster Not significant ### pyflate ### Mean +- std dev: 582 ms +- 9 ms -> 355 ms +- 7 ms: 1.64x faster Significant (t=160.55) ### python_startup ### Mean +- std dev: 8.06 ms +- 0.12 ms -> 7.32 ms +- 0.14 ms: 1.10x faster Significant (t=57.03) ### python_startup_no_site ### Mean +- std dev: 5.10 ms +- 0.04 ms -> 5.29 ms +- 0.05 ms: 1.04x slower Significant (t=-40.36) ### raytrace ### Mean +- std dev: 397 ms +- 5 ms -> 235 ms +- 1 ms: 1.69x faster Significant (t=230.24) ### regex_compile ### Mean +- std dev: 149 ms +- 1 ms -> 110 ms +- 0 ms: 1.35x faster Significant (t=328.04) ### regex_dna ### Mean +- std dev: 160 ms +- 0 ms -> 156 ms +- 1 ms: 1.02x faster Significant (t=34.46) ### regex_effbot ### Mean +- std dev: 2.59 ms +- 0.03 ms -> 2.64 ms +- 0.01 ms: 1.02x slower Significant (t=-14.12) ### regex_v8 ### Mean +- std dev: 19.6 ms +- 0.3 ms -> 16.9 ms +- 0.0 ms: 1.16x faster Significant (t=61.11) ### richards ### Mean +- std dev: 63.5 ms +- 0.7 ms -> 36.8 ms +- 0.6 ms: 1.73x faster Significant (t=224.88) ### scimark_fft ### Mean +- std dev: 329 ms +- 3 ms -> 239 ms +- 1 ms: 1.38x faster Significant (t=216.68) ### scimark_lu ### Mean +- std dev: 137 ms +- 3 ms -> 92 ms +- 2 ms: 1.49x faster Significant (t=109.50) ### scimark_monte_carlo ### Mean +- std dev: 90.2 ms +- 1.5 ms -> 51.6 ms +- 0.4 ms: 1.75x faster Significant (t=197.44) ### scimark_sor ### Mean +- std dev: 165 ms +- 2 ms -> 90 ms +- 1 ms: 1.84x faster Significant (t=295.38) ### scimark_sparse_mat_mult ### Mean +- std dev: 4.50 ms +- 0.17 ms -> 3.21 ms +- 0.02 ms: 1.40x faster Significant (t=59.06) ### spectral_norm ### Mean +- std dev: 128 ms +- 1 ms -> 79 ms +- 0 ms: 1.62x faster Significant (t=295.70) ### sqlalchemy_declarative ### Mean +- std dev: 144 ms +- 4 ms -> 118 ms +- 5 ms: 1.22x faster Significant (t=32.39) ### sqlalchemy_imperative ### Mean +- std dev: 17.6 ms +- 0.3 ms -> 14.5 ms +- 0.1 ms: 1.21x faster Significant (t=66.06) ### sqlite_synth ### Mean +- std dev: 2.32 us +- 0.04 us -> 1.85 us +- 0.03 us: 1.25x faster Significant (t=75.74) ### sympy_expand ### Mean +- std dev: 445 ms +- 2 ms -> 380 ms +- 2 ms: 1.17x faster Significant (t=168.59) ### sympy_integrate ### Mean +- std dev: 20.3 ms +- 0.2 ms -> 17.1 ms +- 0.1 ms: 1.19x faster Significant (t=120.17) ### sympy_str ### Mean +- std dev: 269 ms +- 2 ms -> 235 ms +- 2 ms: 1.14x faster Significant (t=91.30) ### sympy_sum ### Mean +- std dev: 155 ms +- 2 ms -> 137 ms +- 2 ms: 1.13x faster Significant (t=62.20) ### telco ### Mean +- std dev: 5.74 ms +- 0.11 ms -> 4.91 ms +- 0.17 ms: 1.17x faster Significant (t=32.09) ### tornado_http ### Mean +- std dev: 128 ms +- 5 ms -> 100 ms +- 3 ms: 1.27x faster Significant (t=35.73) ### unpack_sequence ### Mean +- std dev: 52.7 ns +- 0.7 ns -> 37.2 ns +- 0.4 ns: 1.42x faster Significant (t=145.84) ### unpickle ### Mean +- std dev: 10.9 us +- 0.1 us -> 10.1 us +- 0.1 us: 1.08x faster Significant (t=61.64) ### unpickle_list ### Mean +- std dev: 3.73 us +- 0.06 us -> 3.41 us +- 0.04 us: 1.09x faster Significant (t=35.50) ### unpickle_pure_python ### Mean +- std dev: 258 us +- 2 us -> 181 us +- 1 us: 1.42x faster Significant (t=228.11) ### xml_etree_generate ### Mean +- std dev: 80.3 ms +- 0.7 ms -> 64.3 ms +- 0.4 ms: 1.25x faster Significant (t=156.04) ### xml_etree_iterparse ### Mean +- std dev: 94.6 ms +- 1.0 ms -> 86.8 ms +- 1.7 ms: 1.09x faster Significant (t=31.06) ### xml_etree_parse ### Mean +- std dev: 141 ms +- 2 ms -> 134 ms +- 3 ms: 1.05x faster Significant (t=12.88) ### xml_etree_process ### Mean +- std dev: 64.4 ms +- 0.6 ms -> 45.1 ms +- 0.5 ms: 1.43x faster Significant (t=187.55)
ワークロードによって異なりますが、おおむね、1.1~1.9倍の実行速度が得られました。
まとめ
Python3.11は、謳い文句通りPythonプログラムの実行の高速化が実現されていました。
実際のワークロードでは、フィボナッチ関数のような単純な関数の場合ほどではないものの、おおよそ1.2倍は高速化され、高速なインスタンス(CPU)への交換や、ソースコードの最適化をまったくせずに高速化できるのですから、お得としか言いようがありませんね。