我正在尝试训练神经网络来玩使用 Pygame 制作的 SMB1 游戏。为了提高速度,我想使用并行处理,以便由不同的群体成员(并在不同的训练数据上)同时玩游戏的多个副本。
我的问题的根源在于 Pygame 本质上并不是基于实例的;也就是说,它只会生成一个带有一个显示对象的窗口。因为我无法创建多个 Pygame 窗口并为每个进程显示对象,所以进程必须共享一个显示对象。这引出了我的第一个问题:有没有办法拥有 pygame 的多个实例,如果没有,是否有一种(性能轻)方法同时在显示器上绘图?也就是说,每个游戏都会绘制到整个窗口的不同部分。
然而,我并不真的需要渲染每个游戏;我只关心至少渲染一个游戏实例,以便我可以监控其进度。我的解决方案是为每个游戏分配一个进程 ID,只有进程 ID 为 0 的游戏才会真正绘制到显示器上。并发问题解决了!为了实现这一点,我使用了 multiprocessing.Process:
processes = [];
genome_batches = np.array_split(genomes,self.runConfig.parallel_processes);
for i in range(runConfig.parallel_processes):
process = multiprocessing.Process(target=self.eval_genome_batch_feedforward,args=(genome_batches[i],config,i));
processes.append(process);
for process in processes:
process.start();
for process in processes:
process.join();
然而,当多处理pickles对象时,这会导致它自己的问题: AttributeError: Can't pickle local object 'RunnerConfig.__init__.<locals>.<lambda>'
注意:config和RunnerConfig是两个不同的东西;一个来自我正在使用的简洁库,它是传递给函数的配置,另一个是我自己的类,它是进程启动的类的属性。
经过一番研究,似乎因为我使用的是类方法,所以多处理pickle了该类,其中包括上面的RunnerConfig,其中包含lambda函数,这些函数是不可pickle的。这是非常难以解决的,因为这些 lambda 函数是专门在self.eval_genome_batch 中使用的。这就引出了第二个问题:是否可以以不需要对外部类进行pickle的方式使用multiprocessing.Process,这样lambda函数就不会被pickle?
最后,经过更多研究,事实证明,我可以使用 pathos.multiprocessing ,而不是使用 pickle 的 multiprocessing ,它使用 dill 。Dill可以腌制 lambda 函数。万岁!
但不是。最后还有一个操你妈的。Pathos.multiprocessing 仅具有来自 multiprocessing 的 .map 和 .map 等效函数,这不允许我控制进程本身。这意味着当调用该函数时,没有办法(据我所知)告诉程序正在运行游戏的进程 ID,以及是否渲染到屏幕。所以最后一个问题是:有没有一种方法可以使用 pathos.multiprocessing.map (或者实际上是任何库并行函数),a) 不会破坏 lambda 函数,b) 可以告诉被调用的函数是哪个进程ID正在被使用?
最后一点:我知道最简单的答案就是不渲染到 Pygame。这将解决所有问题。然而,能够看到项目的进展和学习对我来说非常有用和重要。
所以,我列出了不同的问题,其中任何一个如果得到解决,都可以解决所有问题:
一种在不同线程中使用 pygame 作为多个不同实例的方法,这些实例是从同一进程生成的
一种安全地同时使用 pygame 的显示(并更新时钟)的方法
一种使用 multiprocessing.Process 的方法,这样它不需要腌制方法的类,但仍然可以访问类变量
一个多处理库:
要么不需要 pickle lambda 函数,要么能够
有办法告诉子进程正在使用哪个进程工作人员
慕桂英546537
相关分类