Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PythonRay:如何在工作人员之间共享变量?_Python_Caching_Multiprocessing_Ray - Fatal编程技术网

PythonRay:如何在工作人员之间共享变量?

PythonRay:如何在工作人员之间共享变量?,python,caching,multiprocessing,ray,Python,Caching,Multiprocessing,Ray,我正在开发一个管道,其中包括从机器学习模型中获取预测,我正在尝试使用ray来加速它。输入可能会重复,因此我希望在函数中共享一个缓存,以便此远程函数的所有工作人员都可以共享对缓存的访问,并对其进行搜索和获取值。 像下面这样的 @ray.remote def f(x): #从x创建输入 #工作 未知_y1=[] 获得的_y1=[] 对于索引,枚举中的y(y1): key='|'.join([str(x)代表y中的x.values()])) 如果键入缓存: 已获取_y1.append(缓存的[key]

我正在开发一个管道,其中包括从机器学习模型中获取预测,我正在尝试使用ray来加速它。输入可能会重复,因此我希望在函数中共享一个缓存,以便此远程函数的所有工作人员都可以共享对缓存的访问,并对其进行搜索和获取值。 像下面这样的

@ray.remote
def f(x):
#从x创建输入
#工作
未知_y1=[]
获得的_y1=[]
对于索引,枚举中的y(y1):
key='|'.join([str(x)代表y中的x.values()]))
如果键入缓存:
已获取_y1.append(缓存的[key])
其他:
已获得1.append(np.inf)
未知_y1.附加(促销)
未知_y2=[]
已获得_y2=[]
对于索引,枚举中的y(y2):
key='|'.join([str(x)代表y中的x.values()]))
如果键入缓存:
已获取\u y2.append(缓存的[key])
其他:
已获取\u y2.append(np.inf)
未知_y2.追加(基线)
已知_y1,已知_y2=预测值。预测(未知_y1,未知_y2)
未知索引=0
对于范围内的索引(len(y1)):
如果(获得的_y1[索引]==np.inf):
已获得的指数=已知指数[未知指数]
key='|'.join([str(x)表示y1中的x[index].values())
如果不是(输入缓存):
缓存的[键]=已获取的_y1[索引]
未知索引=未知索引+1
未知索引=0
对于范围内的索引(len(y2)):
如果(获得的_y2[索引]==np.inf):
已获得的_y2[索引]=已知的_y2[未知的_索引]
key='|'.join([str(x)代表y2中的x[index].values())
如果不是(输入缓存):
缓存的[键]=已获取的\u y2[索引]
未知索引=未知索引+1
我尝试通过添加
global-cached创建一个全局字典;cached=dict()
位于我的脚本顶部,但该变量似乎在不同的工作人员之间是不同的版本,并且不共享数据。以前我是用
dogpile.cache.redis
来实现这一点的,但是该区域将不可序列化,因为它使用了线程锁。我还尝试创建一个dict,并使用
ray.put(cached)
将其放入ray的对象存储中,但我想我在某个地方读到了ray

我目前正在尝试从每个辅助进程返回缓存,并将它们合并到主缓存中,然后再次将它们放入对象存储中。
是否有更好的方法在ray workers之间共享字典/缓存?

不幸的是,您没有创建字典/缓存,因此我看不到您是如何进行多重处理的。为了便于论证,我假设您使用的是
多处理
模块中的
类(
concurrent.futures.ProcessPoolExecutor
)。然后,您希望使用一个托管的、可共享的
dict
,如下所示:

来自多处理导入池、管理器的

def init_池(_缓存):
#使用以下全局变量初始化池中的每个进程:
全局缓存
cached=_缓存
def main():
使用Manager()作为管理器:
cached=manager.dict()
将池(initializer=init_Pool,initargs=(cached,))作为池:
... # 创建任务的代码
#Windows要求:
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()
这将在dictionary中使用变量
cached
创建对此dictionary的代理的引用。因此,所有字典访问本质上更类似于远程过程调用,因此执行速度比“正常”字典访问慢得多。只是要知道


如果有其他机制来创建辅助对象(decorator
@ray.remote
?),则
缓存的
变量可以作为参数传递给函数
f

,您可能会对这个关于为ray编写函数缓存的问题/答案感兴趣

您的想法是正确的,但我认为您缺少的关键细节是,您应该使用Ray将全局状态保存在actor或对象存储中(如果是不可变的)

在您的情况下,看起来您正在尝试缓存远程功能的一部分,而不是整个功能。你可能想要这样的东西

这是一个简化的版本,你可以考虑如何编写你的函数。< /P>
@ray.remote
class Cache:
  def __init__(self):
    self.cache = {}

  def put(self, x, y):
    self.cache[x] = y

  def get(self, x):
    return self.cache.get(x)

global_cache = Cache.remote()

@ray.remote
def f(x):
  all_inputs = list(range(x)) # A simplified set of generated inputs based on x
  obtained_output = ray.get([global_cache.get(i) for i in all_inputs])

  unknown_indices = []
  for i, output in enumerate(obtained_output):
    if output is None:
        unknown_inputs.append(i)
 
  # Now go through and calculate all the unknown inputs
  for i in unknown_inputs:
    output = predict(all_inputs[i]) # calculate the output
    global_cache.put.remote(output) # Cache it so it's available next time
    obtained_output[i] = output

  return obtained_output

考虑到OP使用的是ray,假设他们多次调用f.remote(…)可能是安全的。演员会阻止吗?我记得在远程任务中使用
ray.get
时,它通常会阻塞,并且不会完全并行运行,但我不确定演员是否也是这样。不过我要试试这个。非常感谢。