3

Python でのマルチスレッド処理を理解しようとしています。単語数、テキストの行数を計算し、各単語の数で辞書を作成する作業コードがあります。コードのコメントに記載されているような小さなファイルで高速に実行されます。ただし、通常は glob を使用して複数のファイルを取り込みます。私がそうすると、実行時間が大幅に増加しました。一方、私のスクリプトはシングル スレッドだったので、他の 3 つのコアがアイドル状態にあり、1 つが限界に達していることがわかります。

私はpythons multithreadingモジュールを試してみようと思った.

#!/bin/python
#
# test file: http://www.gutenberg.org/ebooks/2852.txt.utf-8

import fileinput
from collections import defaultdict
import threading
import time

inputfilename = 'pg2852.txt'

exitFlag = 0

line = []
line_counter = 0
tot_words = 0
word_dict = defaultdict(int)

def myCounters( threadName, delay):
        for line in fileinput.input([inputfilename]):
                line = line.strip();
                if not line: continue
                words = line.split()
                tot_words += len(words)
                line_counter += 1
                for word in words:
                        word_dict[word] += 1

        print "%s: %s:" %( threadName, time.ctime(time.time()) )
        print word_dict
        print "Total Words: ", tot_words
        print "Total Lines: ", line_counter

try:
        thread.start_new_thread( myCounters, ("Thread-1", 2, ) )
        thread.start_new_thread( myCounters, ("Thread-2", 4, ) )
except:
        print "Error: Thread Not Started"

while 1:
        pass

このコードを試してみても、うまくいきません。入力ファイルをチャンクに分割し、何らかの方法で出力をマージする必要があると思います。? マップ/リデュース? おそらくもっと簡単な解決策がありますか?

編集:

たぶん次のようなもの:

  1. ファイルを開き、
  2. それをチャンクに分割します
  3. 各チャンクを異なるスレッドにフィードする
  4. カウントを取得し、各チャンクで辞書を作成します
  5. マージ数 / dict
  6. 結果を返す
4

1 に答える 1

5

まず第一に、並列スレッドではなく並列プロセスを使用する必要があるというのは正しいことです。この種のタスクを実行すると[以下のETAを参照]、グローバルインタープリターロック(GIL)が原因で、Pythonで複数のスレッドに適切に拡張できません。

単一のファイルを並行して処理する場合、明らかな方法は、最初にファイルサイズを確認してから、同じサイズのチャンクを複数のプロセスに割り当てることです。これには、ファイル内のどの位置から開始し、どの位置で終了するかを各プロセスに指示するだけです。(もちろん、単語や行を2回カウントしないように注意する必要があります。簡単な方法は、各プロセスが行の先頭に到達するまで最初のバイトを無視してからカウントを開始することです)。

ただし、質問の中で、globを使用して複数のファイルを処理すると述べています。したがって、ファイルをチャンク化するという複雑なルートを取り、チャンクをさまざまなプロセスに割り当てる代わりに、より簡単なオプションは、さまざまなファイルをさまざまなプロセスに割り当てることです。


ETA:

Pythonでスレッドを使用することは、長時間ブロックするI/O関数を使用するなどの特定のユースケースに適しています。@uselpaは、処理がI / Oバウンドの場合、スレッドが適切に実行される可能性があることは正しいですが、ボトルネックは実際にはファイルI / Oではなく解析であるため、ここではそうではありません。これは、インタプリタ言語としてのPythonのパフォーマンス特性によるものです。コンパイル言語では、I/Oがボトルネックになる可能性が高くなります。

元のコードに基づいて(pg2852.txtの100個の連結コピーを含むテストファイルを使用して)測定を行ったばかりなので、これらの主張をします。

  • シングルスレッドとして実行すると、ファイルの読み取りと解析に約2.6秒かかりましたが、解析コードをコメントアウトした場合はわずか0.2秒でした。
  • 2つのスレッドを並行して実行する(同じファイルから読み取る)には7.2秒かかりましたが、並行して起動される2つのシングルスレッドプロセスは、両方を完了するのにわずか3.3秒しかかかりませんでした。
于 2012-06-03T10:57:55.807 に答える