更新: steveha の以前の回答の複製を投稿したことをお詫びします。私の読書スキルについて多くを語っています。i/o/バッファリング/ランタイム効果についての私の考えのためだけに、今のところこの回答をオンラインのままにしておきます。
元の投稿:
Python が 1 つの正規表現を適用して 1 つの平方根を計算するのに、標準入力から 1 行を読み取って結果を標準出力 (またはその他の I/O) に出力するのにかかる時間よりも長いとは思えません。
ある時点での I/O はハードドライブから発生し、別のハードドライブまたはユーザーの目のいずれかに移動するため、それが制限要因になるはずです。
I/O は通常、高速化のためにバッファリングされます。通常、バッファはバーストでいっぱいになり、デバイスがさらにデータを提供するのを待っている間、CPU はアイドル状態になります。
これは、アプリケーションのジェネレーターにつながります。入力を 1 行ずつ読み取り、必要に応じて平方数を即座に提供するジェネレータを作成します。これが、合理的な最新のハードウェアの全体的な I/O 速度よりも遅くなるとは思えません。特別なデバイス (組み込み、uController、Raspberry Pi など) を使用している場合はお知らせください)
実行できる最適化の 1 つは、正規表現をプリコンパイルすることです。各テストで同じ正規表現を使用しているため、正規表現の解析は 1 回だけ行います。を行っているため、質問の例は問題ありませんre.findall()
。私は他の読者のために詳しく説明しているだけです。
import sys, re, math
pattern = re.compile(r'\b\d+\b')
def fh_numbers_to_sqrt(fh):
for line in fh:
for i in re.findall(pattern, line):
yield math.sqrt(float(i))
numbers_g = fh_numbers_to_sqrt(sys.stdin)
for num in numbers_g:
print('%.4f' % num)
これにより、すべての正規表現と数学演算が I/O 時間とインターリーブできます。
さて、私たちが本当に最適化して統合することができないのは、reverse
. アルゴリズムは、最後の要素が反転できるようになるまで待機する必要があります。
したがって、呼び出しコードを次のように変更できます。
numbers_g = fh_numbers_to_sqrt(sys.stdin)
for num in reverse(list(numbers_g)):
print('%.4f' % num)
そして、これがあなたが元々持っていたものよりも速いことを願っています. 繰り返しますが、これがより速くなる唯一の理由は、正規表現の解析と計算の実行時間を、標準入力からデータを読み取るのにかかる実時間内に隠したためです。これはまだ I/O が制限されているはずです。実際にはreverse
、標準出力で発生する I/O とインターリーブする可能性があるため、実行時間全体に実際には追加されない可能性があります。壁掛け時計を見ると、このアルゴリズムは時間をまったく使用しない可能性があります。:-)
私の投稿全体を証明または否定するために、スクリプトの開始から行の直前まで、そしてそこから最後までtime.time()
にかかる時間を測定できます。Data = re.findall
私が正しければ、データの読み取りにはほとんどの時間がかかります。そうでない場合は、すべての正規表現検索に必要な時間も測定する価値があります。我々に教えてください。私は興味がある...