5

かなり大きなファイルがあり、1 ~ 1.5 GB のオーダー (ほとんどがログ ファイル) と、csv に簡単に解析できる生データを組み合わせたもので、後でグラフ化して一連のグラフ イメージを生成することになっています。

現在、bash スクリプトを使用して生データを csv ファイルに変換し、グラフ化する必要がある数値のみを含むようにしてから、それを gnuplot スクリプトにフィードしています。しかし、このプロセスは非常に遅いです。cutいくつかのパイプされたstrなどを 1 つのコマンドに置き換えることで、bash スクリプトを高速化しようとしましたawkが、これにより速度は改善されましたが、全体は依然として非常に低速です。

そのため、このプロセスにはもっと優れたツールがあると信じ始めています。私は現在、このプロセスを python+numpy または R で書き直そうとしています。私の友人は、JVM を使用することを提案しました。それを行う場合は、clojure を使用しますが、JVM がどのように機能するかはわかりません。

私はこの種の問題に対処した経験があまりないので、どのように進めればよいかアドバイスをいただければ幸いです。ありがとう。

編集:また、生成された中間データ、つまり csv を (ディスクに) 保存したいので、再生成する必要はありません。

編集 2:生データ ファイルには 1 行に 1 つのレコードがあり、そのフィールドは区切り文字 ( |) で区切られています。すべてのフィールドが数値であるとは限りません。出力csvで必要な各フィールドは、入力レコードに特定の式を適用することによって取得されます。これは、入力データの複数のフィールドを使用する場合があります。出力 csv には 1 行あたり 3 ~ 4 フィールドがあり、1 ~ 2、1 ~ 3、1 ~ 4 フィールドを (場合によっては) 棒グラフにプロットするグラフが必要です。それがより良いイメージを与えることを願っています。

編集 3: @adirau のスクリプトを少し変更しましたが、かなりうまく機能しているようです。データを読み取り、プロセッサ スレッドのプールに送信し (疑似処理、スレッド名をデータに追加)、それを別のコレクタースレッドを介して出力ファイルに集約しています。

PS: この質問のタグ付けについてはよくわかりません。お気軽に修正してください。

4

2 に答える 2

4

pythonは、優れたスレッドAPI(ただし、実装には疑問があります)、matplotlib、およびpylabを備えているため、適切な選択のように思われます。私はあなたの側からいくつかの仕様を見逃していますが、おそらくこれはあなたにとって良い出発点になるかもしれません:matplotlib:スレッドを使った非同期プロット。バルクディスクI/O読み取りを処理し、データ処理のためにスレッドのプールにキューイングを同期するために単一のスレッドを使用します(レコード長が固定されている場合は、読み取りオフセットを事前に計算し、オフセットだけをスレッドプールに渡すことで処理が速くなる可能性があります) ; diskioスレッドを使用して、データソースファイルをmmapし、事前定義されたnumバイトともう1つの読み取りを読み取って、最終的に現在のデータソース行入力の最後まで最後のバイトを取得します。numbytesは、平均行入力長に近い場所で選択する必要があります。次は、キューを介したプールのフィードと、スレッドプールで行われるデータ処理/プロットです。私はここで(あなたが正確に何をプロットしているのか)良い絵を持っていませんが、これが役立つことを願っています。

編集:一度に複数の行を取得するためのfile.readlines([sizehint])があります。ドキュメントが内部でreadline()を使用していると言っているので、それほど高速ではないかもしれません

編集:簡単なスケルトンコード

import threading
from collections import deque
import sys
import mmap


class processor(Thread):
    """
        processor gets a batch of data at time from the diskio thread
    """
    def __init__(self,q):
        Thread.__init__(self,name="plotter")
        self._queue = q
    def run(self):
        #get batched data 
        while True:
            #we wait for a batch
            dataloop = self.feed(self._queue.get())
            try:
                while True:
                    self.plot(dataloop.next())
            except StopIteration:
                pass
            #sanitizer exceptions following, maybe

    def parseline(self,line):
        """ return a data struct ready for plotting """
        raise NotImplementedError

    def feed(self,databuf):
        #we yield one-at-time datastruct ready-to-go for plotting
        for line in databuf:
            yield self.parseline(line)

    def plot(self,data):
        """integrate
        https://www.esclab.tw/wiki/index.php/Matplotlib#Asynchronous_plotting_with_threads
        maybe
        """
class sharedq(object):
    """i dont recall where i got this implementation from 
    you may write a better one"""
    def __init__(self,maxsize=8192):
        self.queue = deque()
        self.barrier = threading.RLock()
        self.read_c = threading.Condition(self.barrier)
        self.write_c = threading.Condition(self.barrier)
        self.msz = maxsize
    def put(self,item):
        self.barrier.acquire()
        while len(self.queue) >= self.msz:
            self.write_c.wait()
        self.queue.append(item)
        self.read_c.notify()
        self.barrier.release()
    def get(self):
        self.barrier.acquire()
        while not self.queue:
            self.read_c.wait()
        item = self.queue.popleft()
        self.write_c.notify()
        self.barrier.release()
        return item



q = sharedq()
#sizehint for readine lines
numbytes=1024
for i in xrange(8):
    p = processor(q)
    p.start()
for fn in sys.argv[1:]
    with open(fn, "r+b") as f:
        #you may want a better sizehint here
        map = mmap.mmap(f.fileno(), 0)
        #insert a loop here, i forgot
        q.put(map.readlines(numbytes))

#some cleanup code may be desirable
于 2011-03-29T07:22:29.507 に答える
1

速度と実装の容易さに関しては、python + Numpyが最も効率的な方法だと思います。Numpy は高度に最適化されているため、パフォーマンスはまともであり、Python はアルゴリズムの実装部分を容易にします。

このコンボは、メモリ上のファイルのロードを最適化する場合にうまく機能するはずです。大きすぎず、読み取りサイクルと書き込みサイクルを最小限に抑えるのに十分な大きさのデータ ブロックを処理する中間点を見つけてください。プログラムを遅くするものです

これをさらに高速化する必要があると思われる場合 (私は心から疑っています)、Cython を使用して遅い部分を高速化できます。

于 2011-03-29T07:33:33.560 に答える