Alternatives to named(array)tuple?
See original GitHub issueThanks for the great library! I’ve been trying to use it for an OpenGL env that doesn’t like being fork()
ed. That rules out using the default fork
context in multiprocessing
, which I’ve had to replace with spawn
. Unfortunately there are several places (Gym env wrapper, Gym space wrapper, buffer_from_example
, etc.) where rlpyt
dynamically creates new namedtuple
or namedarraytuple
types and stores them as globals in some module. spawn
does not preserve globals, so those types cannot be found in the child processes created by multiprocessing
, and the whole thing falls down due to pickle
errors. Although I haven’t tried it, I expect something similar would happen if I tried to pickle buffers (e.g. to store demonstrations to disk) & then reload them in a different interpreter later on. This is a major limitation for my use case.
I’ve gotten around this problem by replacing namedtuple
and namedarraytuple
with duck-type equivalents that don’t create a new type for each possible type name & combination of fields. Roughly it looks like the code below (for namedtuple
; namedarraytuple
is similar):
class NamedTupleSchema:
# instances of this class act a bit like a type returned by namedtuple()
def __init__(self, type_name, fields):
self.type_name = type_name
self._fields = fields
def __call__(self, *values):
# allows instances of `NamedTupleSchema` to act like `namedtuple` constructors
return NamedTuple(self, values)
class NamedTuple(tuple):
# instances of this class act like instances of namedtuple types
def __new__(cls, schema, values):
self = tuple.__new__(cls, values)
self.schema = schema
return self
@property
def __getattr__(self, name):
# remaining methods (_make, _fields, etc.) are similar
return self[self.schema._fields.index(name)]
This is hacky, but was the path of least resistance (e.g. all the buffer pre-allocation code still works fine without me changing anything outside collections.py
). What would you think about incorporating a less hacky solution into rlpyt? I was thinking something along the lines of replacing all the namedtuple
and namedarraytuple
instances with nests of dicts/tuples/etc. The ergonomics of namedarraytuple
could be preserved with a helper dict
wrapper that supports array-based numeric indexing. Perhaps you have better ideas, though.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:4
- Comments:13 (13 by maintainers)
Top GitHub Comments
All patched into master with merge commit: 99fb5b68d7ccbf0caa3c528734fe600340afd6b3 which includes #117. I think that’s all done here, to summarize:
shared memory should now support spawn (previously only fork) in
np_mp_array
(vianp_mp_array_spawn
).pickling/unpickling of data buffers under spawn now supported using e.g. new NamedArrayTuple replacement for namedarraytuple; added new gym env and space wrappers (appended with
_schema
)dynamic creation of namedarraytuple types also may be easier using the schema–no need to get into module globals
Let us know if we missed anything!
@ankeshanand if you want to work on the
mp.Lock()
issue some more, let’s move that to a new issue?Great, thanks for implementing this! I’m a bit busy today & tomorrow, but I should be able to try it out on Thursday afternoon & update this thread then.