20

LRUキャッシュを使用して、かなりヘビーデューティーな処理を高速化しています。それはうまく機能し、物事をかなりスピードアップします。でも...

マルチプロセスを実行すると、各プロセスが独自の個別のキャッシュを作成し、同じもののコピーが8つあります。ボックスのメモリが不足し、結果として悪いことが起こるまで、それは問題ではないようです...

Ideally I only need a cachesize of around 300 items for the application, and 1*300 will fit in the 7GB i have to work with, but the 8*300 just doesn't fit.

How do I get all the processes to share the same cache?

4

2 に答える 2

11

a を使用しManagerて、プロセス間で辞書を共有できると思います。理論的には、すべての関数に同じキャッシュを使用できるはずです。

ただし、より健全なロジックは、キャッシュでクエリを検索することでクエリに応答するプロセスを1 つ持つことであり、クエリが存在しない場合は、作業をサブプロセスに委任し、結果を返す前にキャッシュすることです。あなたは簡単にそれを行うことができます

with concurrent.futures.ProcessPoolExecutor() as e:
    @functools.lru_cache
    def work(*args, **kwargs):
        return e.submit(slow_work, *args, **kwargs)

コンシューマーが待機する必要があるオブジェクトworkを返すことに注意してください。Futureは将来のlru_cacheオブジェクトをキャッシュして、自動的に返されるようにします。彼らのデータには複数回アクセスできると思いますが、今すぐテストすることはできません。

Python 3 を使用していない場合は、バックポートされたバージョンのconcurrent.futuresとをインストールする必要がありfunctools.lru_cacheます。

于 2012-12-04T00:33:55.757 に答える
0

共有キャッシュを各プロセスに渡します。親プロセスは単一のキャッシュをインスタンス化し、それを各プロセスに引数として参照できます...

@utils.lru_cache(maxsize=300)
def get_stuff(key):
    """This is the routine that does the stuff which can be cached.
    """
    return Stuff(key)

def process(stuff_obj):
    """This is the routine which multiple processes call to do work with that Stuff
    """
    # get_stuff(key) <-- Wrong; I was calling the cache from here
    stuff_obj.execute()

def iterate_stuff(keys):
    """This generates work for the processses.
    """
    for key in keys:
        yield get_stuff(key)  # <-- I can call the cache from the parent

def main():
    ...
    keys = get_list_of_keys()
    for result in pool.imap(process, iterate_stuff(keys)):
         evaluate(result)
    ...

プロセスを呼び出す前にキャッシュを検索できるため、この例は単純です。一部のシナリオでは、値ではなくポインターをキャッシュに渡すことを好む場合があります。例えば:

        yield (key, get_stuff)

カトリエルは私を正しい軌道に乗せたので、その答えを実装しますが、愚かなことに、私の間違いは彼が提案したものよりも解決するのがさらに簡単でした.

于 2012-12-04T00:54:53.380 に答える