##はじめに
こんにちは、麻菜結です。Pythonの内包表記が数多あるプログラミング言語の記法の中でも多機能かつ可読性が高く素晴らしい文法なのは間違いありませんが(個人の意見であり多大に偏見を含んでいる可能性があります)、よく競技プログラミングでは以下の記法が見られます。
l = list(map(int, input().split()))
内包表記の敵、map
ですね(偏見を(略)。いちいちlist
かまさないといけないmapがなんぼのもんじゃい!ということで速度を比較してみました。
##環境
wsl1のUbuntuを使います。
$ uname -a
Linux LAPTOP-H6KC5C7N 4.4.0-18362-Microsoft #1049-Microsoft Thu Aug 14 12:01:00 PST 2020 x86_64 x86_64 x86_64 GNU/Linux
$ py --version
Python 3.8.0
##概要
1
10000行5列の非負な整数値が並ぶテキストファイルを用意する。先頭に10000と記述しファイルの列の数とする。
2
timeモジュールのtime()を用いて始まりの時間を記録する。
3
行ごとに内包表記かmapでデータを格納する。
4
data.appendを繰り返して終わったらtime()で時間を取得して2
の値と差分を出しそれを実行時間として表示する。
5
5回ほど試しそれの平均を取り比較する。
##スクリプト
以下のスクリプトを用います。
import time
start = time.time()
n = int(input())
data = []
for _ in range(n):
data.append([int(e) for e in input().split(" ")])
process_time = time.time() - start
print(process_time)
import time
start = time.time()
n = int(input())
data = []
for _ in range(n):
data.append(list(map(int, input().split())))
process_time = time.time() - start
print(process_time)
##検証
五回ぐらい実行してみてその平均を考えてみます。
まずは内包表記です。まぁまずまずですね。
$ for((i=0;i<5;i++)); do cat InputText.txt | py time_comp.py; done
0.0833895206451416
0.07289266586303711
0.08693099021911621
0.12533855438232422
0.09039974212646484
平均すると0.09541くらいでしょうか。
次にmapです。
$ for((i=0;i<5;i++)); do cat InputText.txt | py time_map.py; done
0.0980367660522461
0.08674144744873047
0.11994338035583496
0.08462047576904297
0.08770060539245605
こちらも平均すると0.09541と同じですね。
(いや有意差が無いぞ…内包表記遅いやないかい!で記事書こうと思ったのに)
##追加検証
ラズパイ4でやりました。
$ uname -a
Linux asana 5.4.51-v8+ #1333 SMP PREEMPT Mon Aug 10 16:58:35 BST 2020 aarch64GNU/Linux
$ py --version
Python 3.7.3
$ for((i=0;i<5;i++)); do cat InputText.txt | py time_comp.py; done
0.12080025672912598
0.10874629020690918
0.1127462387084961
0.1103978157043457
0.15588116645812988
$ for((i=0;i<5;i++)); do cat InputText.txt | py time_map.py; done
0.11949372291564941
0.11281895637512207
0.11392450332641602
0.2708289623260498
0.276080846786499
平均を計算すると、内包表記は0.1217、mapは0.1786ぐらいでしょうか。ここでは内包表記が優位になりました。
Windowsでやりました。
> cmd /c ver
Microsoft Windows [Version 10.0.18363.1110]
> py --version
Python 3.8.2
> for($i = 0;$i -le 5; $i++){cat .\InputText.txt | py .\time_comp.py}
1.0488629341125488
0.7845804691314697
1.163966178894043
0.7295846939086914
0.7399096488952637
0.8466687202453613
> for($i = 0;$i -le 5; $i++){cat .\InputText.txt | py .\time_map.py}
0.5758388042449951
0.5823671817779541
0.6683478355407715
0.6919825077056885
0.6597652435302734
0.6140100955963135
Windowsおっそ明らかな有意差が出ましたね、結構OSによる差があるみたいです。
##結論
結論としては、『環境や状況に左右されやすく、どっちが良いとは断言できない。』という感じでしょうか。自分はmapの方が明らかに早いからよくつかわれていているのだと思い込んでいましたが、そういうわけでは無いみたいですね。それともまた他のアーキテクチャやOSでは差が出るのか…inputをsys.stdinにしたら変わるのか、そもそもリストアペンドが遅くて差が隠れてしまっているのではないか、メモリの効率はいかがなのかなど他にも検証事項はありそうですが、この辺でいったん終わりにしたいと思います。
ここまでお読みいただいてありがとうございました。皆さんはどちら派ですか?