2022年12月1日:
UTM 4.0.9のゲストOSでUbuntu 22.10、Python 3.11.0のベンチマークを追加
こんにちは。ナミレリです。みなさん、UbuntuでもPythonは使っていますか?
前回の記事で、M1 Max、M2 Air、Intel Core i7のMacbookでPythonのベンチマークをとりました。シングルコアの性能が高いM2のMacbook Airがほぼ全ての項目で良い結果となりました。2019年のIntel Core i7のほぼ2倍のパフォーマンスです。詳しくは下の記事をご覧ください。
今回は、Parallels Desktop for Mac上のUbuntu22.10で同じPythonのベンチマークをとっていたところ、母艦のM1 Maxより速い結果の項目もあり、そんなこともあるのか!という思いからまとめてみたいと思います。配列アクセス意外はゲストOSの方が速い!というのは意外でした。Parallels Desktop for Macが優秀ということなのか、たまたまなのか・・・。そんな思いからの記事です。
- MacBook Pro 14インチ M1Max(メモリ32GB)
- macOS Ventura 13.0.1
- pyenv 2.3.6
- Python 3.11.0
- Parallels Desktop for Mac(Parallelsの公式サイト)
- Ubuntu22.10(Kinetic Kudu)
- pyenv 2.3.6
- Python 3.11.0
目次
計測環境について
Parallels Desktop for Macの母艦はM1 Maxの14インチMacBook Proで、ゲストOSはUbuntu 22.10です。
M1 Max(Parallelsの母艦)
sysctl -a | grep -e brand_string -e cpu.core_count
machdep.cpu.core_count: 10
machdep.cpu.brand_string: Apple M1 Max
ParallelsのゲストOS(Ubuntu 22.10)
lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.10
Release: 22.10
Codename: kinetic
uname -a
Linux ubuntu-kinetic 5.19.0-23-generic #24-Ubuntu SMP PREEMPT_DYNAMIC Fri Oct 14 15:40:27 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux
はじめに
Python 3.11.0の高速化や新機能については下記サイトを参考にさせていただきました。
また、この記事で比較する処理については下記のサイトを参考にさせていただきました。
1. forループ処理
単純なforによるループ処理を計測してみます。0から100,000,000までの数字をforによりループさせ、それを10回繰り返す処理です。処理が終わったら平均を秒で出力します。
import timeit
def test():
for i in range(n):
pass
n = 100000000 # 10^8
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max(母艦) | 0.945 |
Ubuntu on Parallels 18 for Mac | 0.852 |
Ubuntu 22.10 on UTM | 0.854 |
Parallels Desktop for MacのゲストOS(Ubuntu)が9.8%高速という結果に。
2. 代入処理
上の単純なforによるループ処理に加えて、ans = iの代入を追加したプログラムです。
0から100,000,000までの数字をforによりループさせ、都度その数値をansに代入しています。それを10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def test():
ans = 0
for i in range(n):
ans = i
n = 100000000 # 10^8
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 1.071 |
Ubuntu on Parallels 18 for Mac | 0.995 |
Ubuntu 22.10 on UTM | 0.996 |
Parallels Desktop for MacのゲストOS(Ubuntu)が7.1%高速という結果に。
3. 定数を使った四則演算
0から100,000,000までの数字をforによりループさせ、都度、決まった四則演算を行っています。10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def test():
for i in range(n):
1 + 1
1 - 1
1 * 1
1 // 1
n = 100000000 # 10^8
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 1.107 |
Ubuntu on Parallels 18 for Mac | 0.966 |
Ubuntu 22.10 on UTM | 0.977 |
Parallels Desktop for MacのゲストOS(Ubuntu)が12.7%高速という結果に。
4. 変数を使った四則演算
2から100,000,000までの数字をforによりループさせ、繰り返し変数iを使って四則演算を行っています。10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def test():
for i in range(2, n):
i * (i % (i - 1)) + i
n = 100000000 # 10^8
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 4.832 |
Ubuntu on Parallels 18 for Mac | 4.325 |
Ubuntu 22.10 on UTM | 4.374 |
Parallels Desktop for MacのゲストOS(Ubuntu)が10.5%高速という結果に。
5. if文
0から100,000,000までの数字をforによりループさせ、if文の条件で繰り返し変数iが0だったら、という処理をしています。全体を10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def test():
for i in range(n):
if i == 0:
pass
n = 100000000 # 10^8
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 1.345 |
Ubuntu on Parallels 18 for Mac | 1.255 |
Ubuntu 22.10 on UTM | 1.273 |
Parallels Desktop for MacのゲストOS(Ubuntu)が6.7%高速という結果に。
配列アクセス
6. シーケンシャル
0から100,000,000までのリストAを用意して、順番にリストの要素にアクセスします。全体を10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def test():
A = [i for i in range(n)]
for a in A:
pass
n = 100000000 # 10^8
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 2.111 |
Ubuntu on Parallels 18 for Mac | 21.660 |
Ubuntu 22.10 on UTM | 22.431 |
配列のアクセスについてはParallels Desktop for MacのゲストOS(Ubuntu)がとても遅く、母艦のM1 Maxより10倍遅いという結果に。
7. ランダムアクセス(Read)
0から100,000,000までのリストAを用意して、indexを指定してリストの要素にアクセスします。全体を10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def test():
A = [i for i in range(n)]
for i in range(n):
A[i]
n = 100000000 # 10^8
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 3.063 |
Ubuntu on Parallels 18 for Mac | 25.505 |
Ubuntu 22.10 on UTM | 23.621 |
配列のランダムアクセスもParallels Desktop for MacのゲストOS(Ubuntu)がとても遅く、母艦のM1 Maxより8.3倍遅いという結果に。
8. ランダムアクセス(Write)
0から100,000,000までのリストAを用意して、indexを指定してリストの要素にアクセスします。その要素に0を代入します。全体を10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def test():
A = [i for i in range(n)]
for i in range(n):
A[i] = 0
n = 100000000 # 10^8
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 3.514 |
Ubuntu on Parallels 18 for Mac | 13.500 |
Ubuntu 22.10 on UTM | 5.802 |
配列のランダムアクセスのWriteもParallels Desktop for MacのゲストOS(Ubuntu)がとても遅く、母艦のM1 Maxより3.8倍遅いという結果に。
9. ソート
0から1,000,000までランダムな順番のリストAを用意し、その後リストAをソートします。全体を10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
from random import randint, seed
seed(0)
def test():
A = [randint(1, n) for _ in range(n)]
A.sort()
n = 1000000 # 10^6
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 0.409 |
Ubuntu on Parallels 18 for Mac | 0.413 |
Ubuntu 22.10 on UTM | 0.418 |
母艦のM1 MaxとParallels Desktop for MacのゲストOS(Ubuntu)はほぼ同等の速度です。
文字列結合
10. +による結合
0から10,000,000までの数字をforによりループさせ、都度、文字列aを結合します。10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def test():
ans = ''
for i in range(n):
ans += 'a'
n = 10000000 # 10^7
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 0.464 |
Ubuntu on Parallels 18 for Mac | 0.298 |
Ubuntu 22.10 on UTM | 0.297 |
Parallels Desktop for MacのゲストOS(Ubuntu)が35.8%高速という結果に。
11. joinによる結合
0から10,000,000までのリストA(文字列)を用意して、リストの各要素を区切り文字なしで結合します。10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def test():
A = [str(i) for i in range(n)]
ans = ''.join(A)
n = 10000000 # 10^7
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 0.835 |
Ubuntu on Parallels 18 for Mac | 0.665 |
Ubuntu 22.10 on UTM | 0.657 |
Parallels Desktop for MacのゲストOS(Ubuntu)が20.4%高速という結果に。
モジュール
12. deque
0から10,000,000までのdequeオブジェクトを用意し、0から10,000,000までの数字をforによりループさせ、dequeオブジェクトの先頭の要素を取り出し(que.popleft())、その要素を末尾に追加します(que.append())。10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
from collections import deque
def test():
que = deque(range(n))
for i in range(n):
que.append(que.popleft())
n = 10000000 # 10^7
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 0.405 |
Ubuntu on Parallels 18 for Mac | 0.394 |
Ubuntu 22.10 on UTM | 0.381 |
Parallels Desktop for MacのゲストOS(Ubuntu)が2.7%高速という結果に。ほぼ同じですね。
13. 優先度付きキュー
Python標準ライブラリのheapqを使い、リストqueに0から10,000,000までを優先度付きキューの要素に挿入します。その後、優先度付きキューから最小値を取り出します。この処理を10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
import heapq
def test():
que = [0]
for i in range(n):
heapq.heappush(que, i)
for i in range(n):
heapq.heappop(que)
n = 10000000 # 10^7
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 3.326 |
Ubuntu on Parallels 18 for Mac | 3.729 |
Ubuntu 22.10 on UTM | 3.787 |
Parallels Desktop for MacのゲストOS(Ubuntu)が、母艦のM1 Maxより12.1%遅いという結果に。
14. 組み込み関数呼び出し
0から10,000,000までの数字をforによりループさせ、max関数により繰り返し変数iと0の2つの要素の内、最大値を持つ要素の値を取得します。この処理を10回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def test():
for i in range(n):
max(0, i)
n = 10000000 # 10^7
loop = 10
result = timeit.timeit('test()', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 0.773 |
Ubuntu on Parallels 18 for Mac | 0.737 |
Ubuntu 22.10 on UTM | 0.731 |
Parallels Desktop for MacのゲストOS(Ubuntu)が4.7%高速という結果に。ほぼ同じですね。
15. 再帰関数
40番目のフィボナッチ数列を再帰処理で求めます。3回繰り返し、処理が終わったら平均を秒で出力します。
import timeit
def fibonacci(n):
if n == 0 or n == 1:
return n
else:
return fibonacci(n - 2) + fibonacci(n - 1)
n = 40
loop = 3
result = timeit.timeit('fibonacci(n)', globals=globals(), number=loop)
print(format(result / loop, '.3f'))
Python 3.11.0 | |
M1 Max | 12.174 |
Ubuntu on Parallels 18 for Mac | 13.076 |
Ubuntu 22.10 on UTM | 13.073 |
Parallels Desktop for MacのゲストOS(Ubuntu)が、母艦のM1 Maxより7.4%遅いという結果に。
まとめ
処理 | M1 Max (母艦) Python 3.11.0 | Ubuntu on Parallels 18 Python 3.11.0 | Ubuntu on UTM Python 3.11.0 |
---|---|---|---|
forループ処理 | 0.945 | 0.852 | 0.854 |
代入処理 | 1.071 | 0.995 | 0.996 |
定数を使った四則演算 | 1.107 | 0.966 | 0.977 |
変数を使った四則演算 | 4.832 | 4.325 | 4.374 |
if文 | 1.345 | 1.255 | 1.273 |
配列シーケンシャル | 2.111 | 21.66 | 22.431 |
配列ランダムRead | 3.063 | 25.505 | 23.621 |
配列ランダムWrite | 3.514 | 13.5 | 5.802 |
ソート | 0.409 | 0.413 | 0.418 |
+による結合 | 0.464 | 0.298 | 0.297 |
joinによる結合 | 0.835 | 0.665 | 0.657 |
deque | 0.405 | 0.394 | 0.381 |
優先度付きキュー | 3.326 | 3.729 | 3.787 |
組み込み関数呼び出し | 0.773 | 0.737 | 0.731 |
再帰関数 | 12.174 | 13.076 | 13.073 |
最後に
最後まで読んでいただきありがとうございます。今回のParallels上のUbuntu 22.10でPython 3.11.0のベンチマークをとってみるはいかがでしたでしょうか。母艦のM1 Maxより速い結果の項目もあり、そんなこともあるのか!という思いからまとめてみました。配列アクセス意外はゲストOSの方が速い!というのは意外でした。Parallels Desktop for Macはすごい!ということがわかりました。参考になれば幸いです。
Parallels 19 for Macの無料トライアル もありますので、ぜひダウンロードして試してみてください。Mac上で快適にUbuntuが動作します。MacやLinux、Pythonなど技術系のkindle本も豊富にあります。詳しくはこちらから。
Amazonの電子書籍読み放題サービス「Kindle Unlimited」でプライム会員を対象に、最初の3か月間を無料体験できるキャンペーンを実施中。マンガ、小説、ビジネス書、雑誌など500万冊から、好きな本を何冊でも読めるキャンペーンです。
初めてkindle unlimited 読み放題をご利用の方は30日間の無料で体験できます。
期間終了後は月額980円で、いつでもキャンセルできます。
200万冊以上が読み放題。お好きな端末で利用可能です。