1

Python の初心者 (非常にクール)、最初の質問です。50 MB 以上の ascii ファイルを読み込んで、プロパティ タグをスキャンし、データを numpy 配列に解析しています。ループ全体にタイミング レポートを配置し、原因である np.append() を使用した while ループを見つけました。より速い方法があるかどうか疑問に思います。

これは、デバッグ用の偽のデータを含む入力ファイル形式のサンプルです。

... タグパラメータ char name "Poro" 配列 float データ 100
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 41 42 42 44 45 46 47 48 48 48 49 50 51 52 54 55 56 56 58 59 60 61 62 63 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 81 83 84 85 86 86 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 終了タグ ...

これはコード フラグメントです。ここでは、350k 要素の配列に 70 秒かかっている while ループです。

def readParameter(self, parameterName):
    startTime = time.time()
    intervalTime = time.time()
    token = "tag parameter"
    self.inputBuffer.seek(0)
    for lineno, line in enumerate(self.inputBuffer, 1):
        if token in line:
            line = self.inputBuffer.next().replace('"', '').split()
            elapsedTime = time.time() - intervalTime
            logging.debug("    Time to readParameter find token: " + str(elapsedTime))
            intervalTime = time.time()
            if line[2] == parameterName:
                line = self.inputBuffer.next()
                line = self.inputBuffer.next()
                np.parameterArray = np.fromstring(line, dtype=float, sep=" ")
                line = self.inputBuffer.next()

                **while not "endtag" in line:
                    np.parameterArray = np.append(np.parameterArray, np.fromstring(line, dtype=float, sep=" "))
                    line = self.inputBuffer.next()**

                elapsedTime = time.time() - startTime
                logging.debug("    Time to readParameter load array: " + str(elapsedTime))
                break
    elapsedTime = time.time() - startTime
    logging.debug("    Time to readParameter: " + str(elapsedTime))
    logging.debug(np.parameterArray)
    np.parameterArray = self.make3D(np.parameterArray)
    return np.parameterArray

ありがとう、ジェフ

4

1 に答える 1

4

配列に追加するには、配列のサイズを変更する必要があります。これには、通常、新しい配列を保持するのに十分な大きさの新しいメモリ ブロックを割り当て、既存の配列を新しい場所にコピーし、使用していたメモリを解放する必要があります。これらの操作はすべてコストがかかり、要素ごとに実行しています。350k 要素の場合、基本的にはガベージ コレクター メモリの断片化ストレス テストです。

配列を事前に割り当てます。count パラメーターを取得したので、そのサイズの配列を作成し、ループ内で、新しく解析された要素を追加するのではなく、配列内の次の場所に割り当てるだけです。埋められた要素の数を示す独自のカウンターを保持する必要があります。(代わりに、空の配列の要素を繰り返し処理して置き換えることもできますが、その場合、エラー処理を追加するのが少し難しくなります。)

于 2012-08-28T05:54:33.603 に答える