1

私は次の機能を持っています:

1) hdf5 データセットを整数の ASCII コードとして読み込みます

2) ASCII 整数を文字に変換します... chr() 関数

3) 文字を単一の文字列関数に結合します

プロファイリングを行ったところ、計算の大部分が手順 2 である ASCII 整数から文字への変換に費やされていることがわかりました。以下を使用して、この呼び出しを多少最適化しました。

''.join([chr(x) for x in file[dataSetName].value])

私の解析関数は CPU バウンド (整数から文字への変換) であり、i/o バウンドではないように思われるため、解析に専念するコアの数によって多かれ少なかれ線形速度が向上することを期待していました。1 つのファイルを連続して解析するには ~15 秒かかります... 10 個のファイルを解析するには (12 コアのマシンで)、10 個のスレッドを使用しているときに ~150 秒かかります。つまり、まったく強化されていないように見えます。

次のコードを使用してスレッドを起動しました。

    threads=[]
    timer=[]
    threadNumber=10
    for i,d in enumerate(sortedDirSet):
        timer.append(time.time())
     #   self.loadFile(d,i)
        threads.append(Thread(target=self.loadFileargs=(d,i)))
        threads[-1].start()
        if(i%threadNumber==0):
            for i2,t in enumerate(threads):
                t.join()
                print(time.time()-timer[i2])
            timer=[]
            threads=[]

    for t in threads:
        t.join()

どんな助けでも大歓迎です。

4

2 に答える 2

4

multiprocessingサブプロセスを生成しない限り(たとえば)、Pythonは複数のコアを使用できません(GILのため)。したがって、CPU バウンド タスクのスレッドを生成しても、パフォーマンスが向上することはありません。


multiprocessingandを使用したスクリプトの例を次に示しますqueue

from Queue import Empty # <-- only needed to catch Exception
from multiprocessing import Process, Queue, cpu_count

def loadFile(d, i, queue):
    # some other stuff
    queue.put(result)

if name == "main":
    queue = Queue()
    no = cpu_count()
    processes = []

    for i,d in enumerate(sortedDirSet):
        p = Process(target=self.loadFile, args=(d, i, queue))
        p.start()
        processes.append(p)

        if i % no == 0:
            for p in processes:
                p.join()
            processes = []

    for p in processes:
        p.join()

    results = []
    while True:
        try:
            # False means "don't wait when Empty, throw an exception instead"
            data = queue.get(False)
            results.append(data)
        except Empty:
            break

    # You have all the data, do something with it

もう 1 つの (より複雑な) 方法は、pipeの代わりに使用することですqueue

また、プロセスを生成してから、ジョブ キューを作成し、それらを ( 経由で) サブプロセスに送信する方が効率的pipeです (そのため、毎回プロセスを作成する必要はありません)。しかし、これはさらに複雑になるので、そのままにしておきましょう。

于 2013-04-30T14:35:09.437 に答える
0

Freakish の答えは正しいです。GIL があなたの努力を妨害することになります。

Python 3 を使用する場合は、concurrent.futuresを使用してこれを非常にうまく行うことができます。PyPy もこの機能をバックポートしたと思います。

また、リストの内包表記を置き換えることで、コードの速度を少し上げることができます。

''.join([chr(x) for x in file[dataSetName].value])

地図付き:

''.join(map(chr, file[dataSetName].value))

上記のコードを使用した私のテスト (大規模なランダム リスト) では、リスト内包表記を使用して 15.73 秒、 を使用して 12.44 秒が示されましmapた。

于 2013-04-30T14:56:38.693 に答える