この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは。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)への交換や、ソースコードの最適化をまったくせずに高速化できるのですから、お得としか言いようがありませんね。