为Ray actor功能实现缓存 [英] Implementing cache for Ray actor function

查看:105
本文介绍了为Ray actor功能实现缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是使下面的代码在大约0.3而不是0.5秒的时间内执行.我试过在 foo <上使用 functools.lru_cache toolz.functoolz.memoize kids.cache.cache 中的装饰器/code>,但没有一个起作用(错误消息或未正确执行).我该怎么做才能使这项工作成功?

My goal is to make the code below execute in roughly 0.3 instead of 0.5 seconds. I've tried using the decorators from functools.lru_cache, toolz.functoolz.memoize and kids.cache.cache on foo but none of those has worked (either error message or didn't correctly execute). What can I do to make this work?

import ray


@ray.remote
class Foo:
    def foo(self, x):
        print("executing foo with {}".format(x))
        time.sleep(0.1)


ray.init()
f = Foo.remote()
s = time.time()
ray.get([f.foo.remote(x=i) for i in [1, 2, 1, 4, 1]])
print(time.time()-s)
ray.shutdown()

推荐答案

常规警告:如果函数产生副作用,则缓存任意函数调用可能很危险.

General warning: Caching arbitrary function calls can be dangerous if the function produces side effects.

在这种情况下,大概是您希望程序输出

In this case, presumably you want the program to output

executing foo with 1 
executing foo with 2 
executing foo with 4 

您提到的其他缓存工具不太适合与Ray一起使用,因为它们试图将缓存存储在某种全局状态下,并且没有将该状态存储在可通过分布式方式访问的位置中办法.由于您已经有演员,因此您可以将全局状态存储在演员中.

Those other cache tools you mentioned don't tend to work well with Ray because they try to store the cache in global state of some sort, and they aren't storing that state in a place that can be accessed in a distributed way. Since you already have an actor, you could just store your global state in the actor.

@ray.remote
class Foo:
    def __init__(self):
        self.foo_cache = {}

    def foo(self, x):
        def real_foo(x):
            print("executing foo with {}".format(x))
            time.sleep(0.1)
        if x not in self.foo_cache:
            self.foo_cache[x] = real_foo(x)
        return self.foo_cache[x]

这是一种非常通用的缓存技术,这里唯一重要的区别是我们必须将状态存储在actor中.

This is a pretty generic caching technique, the only important difference here was that we had to store our state in the actor.

我们还可以通过定义通用函数缓存将这种方法推广到任何Ray函数:

We can also generalize this approach for any Ray function by defining a general purpose function cache:

@ray.remote
class FunctionCache:
    def __init__(self, func):
        self.func = ray.remote(func)
        self.cache = {}

    def call(self, *args, **kwargs):
        if (args, kwargs) not in cache:
            cache[(args, kwargs)] = self.func(*args, **kwargs)
        return cache[(args, kwargs)]

然后为了清理使用方式,我们可以定义一个装饰器:

Then to clean up the way we use it we can define a decorator:

class RemoteFunctionLookAlike:
    def __init__(self, func):
        self.func = func

    def remote(self, *args, **kwargs):
        return self.func(*args, **kwargs)


def ray_cache(func):
    cache = FunctionCache.remote(func)
    def call_with_cache(*args, **kwargs):
        return cache.call.remote(*args, **kwargs)
    return RayFunctionLookAlike(call_with_cache)

最后,要使用此缓存:

@ray_cache
def foo(x):
    print("Function called!")
    return abc

ray.get([foo.remote("constant") for _ in range(100)]) # Only prints "Function called!" once.

这篇关于为Ray actor功能实现缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆