0

Tornado アプリケーション コンテキストで非同期に実行したい、重い計算ジョブを処理する関数があると想像してください。さらに、結果をディスクに保存し、同じ引数に対して関数を 2 回再実行しないことで、関数を遅延評価したいと考えています。

結果 (メモ化) をキャッシュしないと、次のようになります。

def complex_computation(arguments):
    ...
    return result

@gen.coroutine
def complex_computation_caller(arguments):
    ...
    result = complex_computation(arguments)
    raise gen.Return(result)

関数のメモ化を実現するために、 joblibからMemoryクラスを選択します。関数を関数で装飾するだけで、簡単にメモ化できます。@mem.cache

@mem.cache
def complex_computation(arguments):
    ...
    return result

memようなものがありますmem = Memory(cachedir=get_cache_dir())

ここで、エグゼキューターで計算的に複雑な関数を実行する場合、2 つを組み合わせることを検討してください。

class TaskRunner(object):
    def __init__(self, loop=None, number_of_workers=1):
        self.executor = futures.ThreadPoolExecutor(number_of_workers)
        self.loop = loop or IOLoop.instance()

    @run_on_executor
    def run(self, func, *args, **kwargs):
        return func(*args, **kwargs)

mem = Memory(cachedir=get_cache_dir())
_runner = TaskRunner(1)

@mem.cache
def complex_computation(arguments):
    ...
    return result

@gen.coroutine
def complex_computation_caller(arguments):
    result = yield _runner.run(complex_computation, arguments)
    ...
    raise gen.Return(result)

最初の質問は、前述のアプローチが技術的に正しいかどうかです。

ここで、次のシナリオを考えてみましょう。

@gen.coroutine
def first_coroutine(arguments):
    ...
    result = yield second_coroutine(arguments)
    raise gen.Return(result)

@gen.coroutine
def second_coroutine(arguments):
    ...
    result = yield third_coroutine(arguments)
    raise gen.Return(result)

2 番目の質問は、どのようにメモ化できるかということですsecond_coroutine。次のようなことをするのは正しいですか:

@gen.coroutine
def first_coroutine(arguments):
    ...
    mem = Memory(cachedir=get_cache_dir())
    mem_second_coroutine = mem(second_coroutine)
    result = yield mem_second_coroutine(arguments)
    raise gen.Return(result)

@gen.coroutine
def second_coroutine(arguments):
    ...
    result = yield third_coroutine(arguments)
    raise gen.Return(result)

[UPDATE I] Tornado での関数の結果のキャッシュと再利用では、2 番目の質問の解決策としてfunctools.lru_cacheorの使用について説明しています。repoze.lru.lru_cache

4

1 に答える 1