* add monitor to the rollout envs in her RUN BENCHMARKS her * Slice -> Slide in her benchmarks RUN BENCHMARKS her * run her benchmark for 200 epochs * dummy commit to RUN BENCHMARKS her * her benchmark for 500 epochs RUN BENCHMARKS her * add num_timesteps to her benchmark to be compatible with viewer RUN BENCHMARKS her * add num_timesteps to her benchmark to be compatible with viewer RUN BENCHMARKS her * add num_timesteps to her benchmark to be compatible with viewer RUN BENCHMARKS her * disable saving of policies in her benchmark RUN BENCHMARKS her * run fetch benchmarks with ppo2 and ddpg RUN BENCHMARKS Fetch * run fetch benchmarks with ppo2 and ddpg RUN BENCHMARKS Fetch * launcher refactor wip * wip * her works on FetchReach * her runner refactor RUN BENCHMARKS Fetch1M * unit test for her * fixing warnings in mpi_average in her, skip test_fetchreach if mujoco is not present * pickle-based serialization in her * remove extra import from subproc_vec_env.py * investigating differences in rollout.py * try with old rollout code RUN BENCHMARKS her * temporarily use DummyVecEnv in cmd_util.py RUN BENCHMARKS her * dummy commit to RUN BENCHMARKS her * set info_values in rollout worker in her RUN BENCHMARKS her * bug in rollout_new.py RUN BENCHMARKS her * fixed bug in rollout_new.py RUN BENCHMARKS her * do not use last step because vecenv calls reset and returns obs after reset RUN BENCHMARKS her * updated buffer sizes RUN BENCHMARKS her * fixed loading/saving via joblib * dust off learning from demonstrations in HER, docs, refactor * add deprecation notice on her play and plot files * address comments by Matthias
115 lines
3.9 KiB
Python
115 lines
3.9 KiB
Python
import numpy as np
|
|
from multiprocessing import Process, Pipe
|
|
from . import VecEnv, CloudpickleWrapper
|
|
|
|
def worker(remote, parent_remote, env_fn_wrapper):
|
|
parent_remote.close()
|
|
env = env_fn_wrapper.x()
|
|
try:
|
|
while True:
|
|
cmd, data = remote.recv()
|
|
if cmd == 'step':
|
|
ob, reward, done, info = env.step(data)
|
|
if done:
|
|
ob = env.reset()
|
|
remote.send((ob, reward, done, info))
|
|
elif cmd == 'reset':
|
|
ob = env.reset()
|
|
remote.send(ob)
|
|
elif cmd == 'render':
|
|
remote.send(env.render(mode='rgb_array'))
|
|
elif cmd == 'close':
|
|
remote.close()
|
|
break
|
|
elif cmd == 'get_spaces':
|
|
remote.send((env.observation_space, env.action_space))
|
|
else:
|
|
raise NotImplementedError
|
|
except KeyboardInterrupt:
|
|
print('SubprocVecEnv worker: got KeyboardInterrupt')
|
|
finally:
|
|
env.close()
|
|
|
|
|
|
class SubprocVecEnv(VecEnv):
|
|
"""
|
|
VecEnv that runs multiple environments in parallel in subproceses and communicates with them via pipes.
|
|
Recommended to use when num_envs > 1 and step() can be a bottleneck.
|
|
"""
|
|
def __init__(self, env_fns, spaces=None):
|
|
"""
|
|
Arguments:
|
|
|
|
env_fns: iterable of callables - functions that create environments to run in subprocesses. Need to be cloud-pickleable
|
|
"""
|
|
self.waiting = False
|
|
self.closed = False
|
|
nenvs = len(env_fns)
|
|
self.remotes, self.work_remotes = zip(*[Pipe() for _ in range(nenvs)])
|
|
self.ps = [Process(target=worker, args=(work_remote, remote, CloudpickleWrapper(env_fn)))
|
|
for (work_remote, remote, env_fn) in zip(self.work_remotes, self.remotes, env_fns)]
|
|
for p in self.ps:
|
|
p.daemon = True # if the main process crashes, we should not cause things to hang
|
|
p.start()
|
|
for remote in self.work_remotes:
|
|
remote.close()
|
|
|
|
self.remotes[0].send(('get_spaces', None))
|
|
observation_space, action_space = self.remotes[0].recv()
|
|
self.viewer = None
|
|
self.specs = [f().spec for f in env_fns]
|
|
VecEnv.__init__(self, len(env_fns), observation_space, action_space)
|
|
|
|
def step_async(self, actions):
|
|
self._assert_not_closed()
|
|
for remote, action in zip(self.remotes, actions):
|
|
remote.send(('step', action))
|
|
self.waiting = True
|
|
|
|
def step_wait(self):
|
|
self._assert_not_closed()
|
|
results = [remote.recv() for remote in self.remotes]
|
|
self.waiting = False
|
|
obs, rews, dones, infos = zip(*results)
|
|
return _flatten_obs(obs), np.stack(rews), np.stack(dones), infos
|
|
|
|
def reset(self):
|
|
self._assert_not_closed()
|
|
for remote in self.remotes:
|
|
remote.send(('reset', None))
|
|
return _flatten_obs([remote.recv() for remote in self.remotes])
|
|
|
|
def close_extras(self):
|
|
self.closed = True
|
|
if self.waiting:
|
|
for remote in self.remotes:
|
|
remote.recv()
|
|
for remote in self.remotes:
|
|
remote.send(('close', None))
|
|
for p in self.ps:
|
|
p.join()
|
|
|
|
def get_images(self):
|
|
self._assert_not_closed()
|
|
for pipe in self.remotes:
|
|
pipe.send(('render', None))
|
|
imgs = [pipe.recv() for pipe in self.remotes]
|
|
return imgs
|
|
|
|
def _assert_not_closed(self):
|
|
assert not self.closed, "Trying to operate on a SubprocVecEnv after calling close()"
|
|
|
|
|
|
def _flatten_obs(obs):
|
|
assert isinstance(obs, list) or isinstance(obs, tuple)
|
|
assert len(obs) > 0
|
|
|
|
if isinstance(obs[0], dict):
|
|
import collections
|
|
assert isinstance(obs, collections.OrderedDict)
|
|
keys = obs[0].keys()
|
|
return {k: np.stack([o[k] for o in obs]) for k in keys}
|
|
else:
|
|
return np.stack(obs)
|
|
|