为了账号安全,请及时绑定邮箱和手机立即绑定

在 python 中使用 Pygame 进行并行处理

在 python 中使用 Pygame 进行并行处理

杨__羊羊 2023-10-25 10:44:15
我正在尝试训练神经网络来玩使用 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 函数,要么能够有办法告诉子进程正在使用哪个进程工作人员
查看完整描述

1 回答

?
慕桂英546537

TA贡献1848条经验 获得超10个赞

我将尝试解决主要问题。我对您的实际问题的理解非常有限,因为我不知道您的代码实际上是做什么的。

“一种在不同线程中使用 pygame 作为多个不同实例的方法,这些实例是从同一进程生成的”

这不起作用,因为 pygame 是基于SDL2构建的,SDL2 声明“您不应期望能够在主线程以外的任何线程上创建窗口、渲染或接收事件”。

“一种安全地同时使用 pygame 的显示(和更新时钟)的方法”

与上面相同,显示仅在主线程中工作。

“一种使用 multiprocessing.Process 的方法,这样它不需要腌制方法的类,但仍然可以访问类变量”

您可以使用类似的方法来pickle这些方法dill,但在进程之间复制python对象的完整内容(对我来说)是错误的。我会寻求另一种解决方案。

“一个多处理库:”

1.要么不需要 pickle lambda 函数,要么能够

您需要使用序列化 Python 对象才能在进程之间发送它们。

2.有办法告诉子进程正在使用哪个进程worker

我不明白这是什么意思。


在我看来,这个问题可以通过更好地分离数据和可视化来解决。培训不应该了解任何可视化,因为它不依赖于您想要如何显示它。所以不应该有任何理由共享 pygame 显示。

完成此操作后,执行您想要执行的操作应该不会有太大问题(多线程总是会导致问题)。关于泡菜问题;我会尽量避免 pickling Python 对象和函数,而只是在线程和进程之间传递基本原语。看来您应该能够self.fitnessFromArray使用简单的int方法进行分配,并根据其值在线程/进程中进行最小/平均/最大计算。

如果你想进行线程化,那么主线程将负责渲染。它还会生成用于训练的线程。当线程完成时,它们将返回结果(或将其放入线程安全存储中),主线程将轮询数据并显示结果。如果训练完成的工作花费的时间超过一帧,则划分工作,以便每个线程仅进行部分训练,并且可以在下一帧停止的地方继续。

如果您想要单独的进程,则原理是相同的。主进程启动几个训练进程并通过套接字连接到它们。从套接字中,您可以轮询有关程序状态的信息并显示它。它基本上是一个客户端-服务器架构(尽管在本地主机上),其中训练脚本是服务器,主进程是客户端。


查看完整回答
反对 回复 2023-10-25
  • 1 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信