Python Ray:固定在内存中的对象无法驱逐

问题描述

我已经创建了一个自定义 NSGA2 算法,并且我正在为我的评估器使用 ray。我注意到我从 ray 任务中检索到的对象被固定,我尝试做一些事情,例如复制返回的对象并删除对原始对象的引用,使用垃圾收集器,或者只是删除对 ray 的所有引用对象使用后但没有运气。

使用光线内存时,我多次获得此输出(从每次评估迭代中):

Driver  f7dc3a80d7a578ceffffffffffffffffffffffff0100000001000000    47.9 MiB    PINNED_IN_MEMORY    /root/anaconda3/envs/myenv/lib/python3.8/site-packages/ray/_private/client_mode_hook.py:wrapper:62 | Optimizer/components.py:evaluate_all:511 | Optimizer/components.py:evaluate_all:159 | Optimizer/components.py:iterate:134

函数在多个区域被调用

class MapEvaluator:
      def __init__(...):
      def evaluate_all(...):
        ....
        results = []
        for i in range(len(chromosomes)):
            trial_idx = int(n_gen*population_size) + i
            offspring[i].trial_idx = trial_idx
            results.append(get_genes.remote(predictor,chromosomes[i],trial_idx,n_gen))

        chromosomes,evaluation,updates_pgScanCaseRate,cache = zip(*ray.get([result for result in results])) # this is line 511 from the above output
       .....
        del chromosomes,cache
       ....
      return offspring

然后它会做一些工作并返回一个对象,该对象引用了从 ray 中检索到的一些对象。我尝试复制需要返回的对象,但似乎不起作用。

2&3)

class NSGAII:
    def __init__(...):
    ....
    def iterate(...):
        ....
         offspring = self.evaluate_all(parents) # calls function below # line 134 from ray memory output
        
        offspring.extend(self.population)

    def evaluate_all(...):
         for parent in parents:
             offspring.extend(self.evaluator.evaluate_all(parent,n_gen,self.variator,self.breeding,self.population_size)) # line 159 from ray memory output
             #self.evaluator.evaluate_all calls the function from 1) from the evaluator class 

主要问题是我按顺序运行 GA(即一个一个地进行多次运行) 例如

for problem in problems:
    run_optimization()

并且上次运行的对象被固定。我已经阅读了有关内存管理的文档,他们提到了许多固定对象的方法,但实际上并没有任何补救措施。

然后我查看了源代码,找到了函数 ray.internal.internal_api.freeray.internal.internal_api.global_gc 并尝试了它们,但它们都不起作用

解决方法

PINNED_IN_MEMORY 表示在某处,代码持有一个指向共享内存的指针。可能发生这种情况的一种常见情况是,当对象的值是一个 numpy 数组时,该数组以零个副本进行访问。所以最有可能的问题是这一行:

        chromosomes,evaluation,updates_pgScanCaseRate,cache = zip(*ray.get([result for result in results])) # this is line 511 from the above output

虽然这些变量稍后会被 del 删除,但很可能是其他变量(可能是返回值 offspring?)持有对其中一个的引用。进行复制可能无济于事,因为它不是深度复制(复制对象指针而不是共享内存中的值)。

您可以通过对 ray.get 返回的值进行深拷贝来释放对象存储内存。但如果您不需要其他对象的额外对象存储内存,我也会考虑保留您当前的代码;复制值会增加额外的开销