2014-01-14 7 views
8

スレッドWhy is reading lines from stdin much slower in C++ than Python?を調べているうちに、私は驚くべきpythonの動作を発見しました。メッシュのpythonコードが分解されたものより遅いのはなぜですか?

は、私はそれがスピード11.5M LPSで動作し、そのスレッド

#!/usr/bin/env python 
from __future__ import print_function 
import time 
import sys 


count = 0 
start_time = time.time() 

for line in sys.stdin: 
    count += 1 

delta_sec = time.time() - start_time 
if delta_sec >= 0: 
    lines_per_sec = int(round(count/delta_sec)) 
    print("Read {0:n} lines in {1:.2f} seconds. LPS: {2:n}".format(count, delta_sec, lines_per_sec)) 

から、簡単なPythonのコードを実行した場合、私は、単一の機能にスクリプト全体を分解する際に

#!/usr/bin/env python 
from __future__ import print_function 
import time 
import sys 


def test(input): 
    count = 0 
    start_time = time.time() 

    for line in input: 
     count += 1 

    delta_sec = time.time() - start_time 
    if delta_sec >= 0: 
     lines_per_sec = int(round(count/delta_sec)) 
     print("Read {0:n} lines in {1:.2f} seconds. LPS: {2:n}".format(count, delta_sec, lines_per_sec)) 


if __name__ == "__main__": 
    test(sys.stdin) 

コードが23MにスピードアップLPS。

なぜこの単純なリファクタリングが私のコードを2倍速くするのですか?

私は、Ubuntu 13.10でpython2.7でテストを実行しました。

+0

ローカル対グローバル – SethMMorton

+1

最初のスクリプトで 'input = sys.stdin for line in input:...'を試してください –

+0

このメソッドは最初のスクリプトを高速化しません –

答えて

4

バイトコードを見ると、この質問に答えるのに役立ちました。最初のスクリプトの一部を操作するため バイトコードは、次のとおり

10   58 SETUP_LOOP    27 (to 88) 
      61 LOAD_NAME    3 (sys) 
      64 LOAD_ATTR    6 (stdin) 
      67 GET_ITER   
     >> 68 FOR_ITER    16 (to 87) 
      71 STORE_NAME    7 (line) 
11   74 LOAD_NAME    4 (count) 
      77 LOAD_CONST    4 (1) 
      80 INPLACE_ADD  
      81 STORE_NAME    4 (count) 
      84 JUMP_ABSOLUTE   68 
     >> 87 POP_BLOCK 

そして第二のスクリプトの一部に対応するためのバイトコードである:

12   18 SETUP_LOOP    24 (to 45) 
      21 LOAD_FAST    0 (input) 
      24 GET_ITER 
     >> 25 FOR_ITER    16 (to 44) 
      28 STORE_FAST    3 (line) 
13   31 LOAD_FAST    1 (count) 
      34 LOAD_CONST    2 (1) 
      37 INPLACE_ADD 
      38 STORE_FAST    1 (count) 
      41 JUMP_ABSOLUTE   25 
     >> 44 POP_BLOCK 

私はこのコード間の実際の差がLOAD_FAST対LOAD_NAMEであることを確認し、 STORE_NAME対STORE_FASTオペコードを使用しています。 文書http://docs.python.org/2.7/library/dis.html#opcode-LOAD_FASTによると、 はLOAD_FASTが索引のみを使用して検索を行い、LOAD_NAMEは変数名を文字列名で検索します。 最初のアプローチは2倍高速です。

+0

興味深い!バイトコードを逆アセンブルするのにあなたは何を使いましたか? – JJC

+1

標準のpython 'dis'モジュールはほぼすべてを逆アセンブルできます:) –

関連する問題