Python 多处理建议和停止进程
我正在尝试实施一个系统,其中:Python 多处理建议和停止进程,python,multiprocessing,Python,Multiprocessing,我正在尝试实施一个系统,其中: Actors生成数据 Replay是一个管理由参与者生成的数据的类(理论上它比下面的代码做得更多,但我在这里发布它时保持了简单) Learner使用Replay类的数据(有时更新Replay的一些数据) 为了实现这一点,我将生成的参与者数据附加到一个多处理.Queue,我使用一个进程将数据推送到重播中。我使用了一个multiprocessing.BaseManager来共享Replay 这是我的实现(代码正在运行): 导入时间 随机输入 从集合导入deque
生成数据Actors
是一个管理由Replay
参与者生成的数据的类(理论上它比下面的代码做得更多,但我在这里发布它时保持了简单)
使用Replay类的数据(有时更新Learner
的一些数据)Replay
多处理.Queue
,我使用一个进程将数据推送到重播中。我使用了一个multiprocessing.BaseManager
来共享Replay
这是我的实现(代码正在运行):
导入时间
随机输入
从集合导入deque
导入torch.multiprocessing作为mp
从multiprocessing.managers导入BaseManager
T=20
B=5
重播\u最小\u大小=10
重播\u最大\u大小=100
班级演员:
定义初始化(自、全局缓冲区、秩):
self.rank=等级
self.local_buffer=[]
self.global\u buffer=全局\u buffer
def运行(自我、数量步数):
对于步进范围(num_步数):
data=f'{self.rank}{step}'
self.local\u buffer.append(数据)
如果len(自本地_缓冲区)>=B:
self.global\u buffer.put(self.local\u buffer)
self.local_buffer=[]
班级学员:
定义初始化(自我,重播):
self.replay=replay
def运行(自我、数量步数):
而self.replay.size()我发现在处理多进程时,最好为每个正在运行的进程设置一个队列。当您准备关闭应用程序时,可以向每个队列发送退出消息(或毒药丸),并干净地关闭每个进程
启动子进程时,通过继承将父队列和子队列传递给新进程。我将尝试看看是否会实现这一点,但由于目标是使所有数据聚合到重播,因此我认为只有一个队列非常好。为什么你认为最好有几个?我不理解关于子进程、父进程和子队列的句子,你能再解释一下吗?我明白了,我会确保所有子进程都引用了重播队列,从而引用了重播进程。父进程将是第一个启动的进程,子进程将是由父进程启动的进程。在这种情况下,尤其是在使用Actor范式时,父进程应该始终管理它启动的子进程。看看这部电影吧,他们已经实现了很多这方面的东西(队列管理),所以你不必这么做。
import time
import random
from collections import deque
import torch.multiprocessing as mp
from multiprocessing.managers import BaseManager
T = 20
B = 5
REPLAY_MINIMUM_SIZE = 10
REPLAY_MAXIMUM_SIZE = 100
class Actor:
def __init__(self, global_buffer, rank):
self.rank = rank
self.local_buffer = []
self.global_buffer = global_buffer
def run(self, num_steps):
for step in range(num_steps):
data = f'{self.rank}_{step}'
self.local_buffer.append(data)
if len(self.local_buffer) >= B:
self.global_buffer.put(self.local_buffer)
self.local_buffer = []
class Learner:
def __init__(self, replay):
self.replay = replay
def run(self, num_steps):
while self.replay.size() <= REPLAY_MINIMUM_SIZE:
time.sleep(0.1)
for step in range(num_steps):
batch = self.replay.sample(B)
print(batch)
class Replay:
def __init__(self, capacity):
self.memory = deque(maxlen=capacity)
def push(self, experiences):
self.memory.extend(experiences)
def sample(self, n):
return random.sample(self.memory, n)
def size(self):
return len(self.memory)
def send_data_to_replay(global_buffer, replay):
while True:
if not global_buffer.empty():
batch = global_buffer.get()
replay.push(batch)
if __name__ == '__main__':
num_actors = 2
global_buffer = mp.Queue()
BaseManager.register("ReplayMemory", Replay)
Manager = BaseManager()
Manager.start()
replay = Manager.ReplayMemory(REPLAY_MAXIMUM_SIZE)
learner = Learner(replay)
learner_process = mp.Process(target=learner.run, args=(T,))
learner_process.start()
actor_processes = []
for rank in range(num_actors):
p = mp.Process(target=Actor(global_buffer, rank).run, args=(T,))
p.start()
actor_processes.append(p)
replay_process = mp.Process(target=send_data_to_replay, args=(global_buffer, replay,))
replay_process.start()
learner_process.join()
[actor_process.join() for actor_process in actor_processes]
replay_process.join()