3

私はPythonを初めて使用し、点群データを他のプログラムからAutodesk Mayaに持ち込むことができるスクリプトを作成しています。スクリプトは正常に機能していますが、私がやろうとしているのはスクリプトを高速化することです。番号付きファイルのリストを反復処理する for ループがあります。つまり、datafile001.txt、datafile002.txt などです。おそらくスレッドまたはキューを使用して、一度に複数のことを行う方法があるかどうか疑問に思っているのですか? 以下に、私が取り組んでいるコードを示します。

     def threadedFuntion(args):
         if len(sourceFiles) > 3:
             for count, item in enumerate(sourceFiles):
                     t1=Thread(target=convertPcToPdc,args=(sourceFiles[filenumber1], particlesName, startframe, endframe, pdcIncrements, outputDirectory, variableFolder, acceptableArrayforms, dataType))
                     t1.start()
                     t2=Thread(target=convertPcToPdc,args=(sourceFiles[filenumber2], particlesName, startframe, endframe, pdcIncrements, outputDirectory, variableFolder, acceptableArrayforms, dataType))
                     t2.start()
                     t3=Thread(target=convertPcToPdc,args=(sourceFiles[filenumber3], particlesName, startframe, endframe, pdcIncrements, outputDirectory, variableFolder, acceptableArrayforms, dataType))
                     t3.start()
                     t4=Thread(target=convertPcToPdc,args=(sourceFiles[filenumber4], particlesName, startframe, endframe, pdcIncrements, outputDirectory, variableFolder, acceptableArrayforms, dataType))
                     t4.start()

これは明らかにいくつかの理由で機能しません。まず、4 つのスレッドしか作成されません。多かれ少なかれオプションを提供できるようにしたいと考えています。次に、スレッドを再利用しようとしているためにエラーが発生しますか? 私が言ったように、私はPythonにまったく慣れておらず、頭を少し超えています。ここでいくつかの投稿を読んでいますが、1つを完全に機能させることはできません。キューは必要なものかもしれないと思いますが、よくわかりませんでした.条件ステートメントと結合ステートメントを試しましたが、もう一度欲しいものを得ることができませんでした.

私が達成したいことは、関数がテキストファイルを読み込んで座標を取得し、それらをバイナリファイルとしてエクスポートしてMayaが読み取ることができるようにすることです。これらのテキスト ファイルの 1 つに 500 万から 1000 万の x、y、z 座標が含まれていることはよくあることで、これにはかなりの時間がかかります。かなりひどいコンピューターで 1 つのファイルを処理するのに約 30 分~1 時間かかります。タスク マネージャーによると、Python は 12% のプロセッサと約 1% の RAM しか使用していません。より多くのファイルがより速く処理されます。forループをマルチスレッド/キューに入れるのは難しいとは思いませんが、約1週間、道に迷って失敗した解決策を試していました。

本当に感謝しています。このウェブサイトは素晴らしいと思います。初めての投稿ですが、ここまで読んだだけで完全に Python を学習した気分です。

4

2 に答える 2

1

threading.Thread をサブクラス化し、作業関数をそのクラスに run() の一部として配置します。

import threading
import time
import random

class Worker(threading.Thread):
    def __init__(self, srcfile, printlock,**kwargs):
        super(Worker,self).__init__(**kwargs)
        self.srcfile = srcfile
        self.lock = printlock # so threads don't step on each other's prints

    def run(self):
        with self.lock:
            print("starting %s on %s" % (self.ident,self.srcfile))
        # do whatever you need to, return when done
        # example, sleep for a random interval up to 10 seconds
        time.sleep(random.random()*10)
        with self.lock:
            print("%s done" % self.ident)


def threadme(srcfiles):
    printlock = threading.Lock()
    threadpool = []
    for file in srcfiles:
        threadpool.append(Worker(file,printlock))

    for thr in threadpool:
        thr.start()

    # this loop will block until all threads are done
    # (however it won't necessarily first join those that are done first)
    for thr in threadpool:
        thr.join()

    print("all threads are done")

if __name__ == "__main__":
    threadme(["abc","def","ghi"])

要求に応じて、スレッドの数を制限するには、次を使用します。

def threadme(infiles,threadlimit=None,timeout=0.01):
    assert threadlimit is None or threadlimit > 0, \
           "need at least one thread";
    printlock = threading.Lock()
    srcfiles = list(infiles)
    threadpool = []

    # keep going while work to do or being done
    while srcfiles or threadpool:

        # while there's room, remove source files
        # and add to the pool
        while srcfiles and \
           (threadlimit is None \
            or len(threadpool) < threadlimit):
            file = srcfiles.pop()
            wrkr = Worker(file,printlock)
            wrkr.start()
            threadpool.append(wrkr)

        # remove completed threads from the pool
        for thr in threadpool:
            thr.join(timeout=timeout)
            if not thr.is_alive():
                threadpool.remove(thr)

    print("all threads are done")

if __name__ == "__main__":
    for lim in (1,2,3,4):
        print("--- Running with thread limit %i ---" % lim)
        threadme(("abc","def","ghi"),threadlimit=lim)

これは実際にはソースを逆に処理することに注意してください (リスト pop() のため)。それらを順番に実行する必要がある場合は、どこかでリストを逆にするか、deque と popleft() を使用します。

于 2012-10-13T01:25:39.093 に答える
0

これにはmrjobを使用することをお勧めします。

Mr Job はmap reduceの Python 実装です。

以下は、多数のテキスト ファイルに対してマルチスレッド ワード カウントを実行する mr ジョブ コードです。

from mrjob.job import MRJob

class MRWordCounter(MRJob):
    def get_words(self, key, line):
        for word in line.split():
            yield word, 1

    def sum_words(self, word, occurrences):
        yield word, sum(occurrences)

    def steps(self):
        return [self.mr(self.get_words, self.sum_words),]

if __name__ == '__main__':
    MRWordCounter.run()

このコードは、すべてのファイルを並行してマップし (各ファイルの単語をカウントします)、さまざまなカウントを 1 つの合計単語カウントに減らします。

于 2012-10-13T00:56:39.327 に答える