def run(game, state=None, entry=None, **kwargs): client = docker.from_env() remote_command = [ 'retro-contest-remote', 'run', game, *([state] if state else []), '-b', 'results/bk2', '-m', 'results' ] agent_command = [] agent_name = kwargs.get('agent', 'agent') datamount = {} if kwargs.get('wallclock_limit') is not None: remote_command.extend(['-W', str(kwargs['wallclock_limit'])]) if kwargs.get('timestep_limit') is not None: remote_command.extend(['-T', str(kwargs['timestep_limit'])]) if kwargs.get('discrete_actions'): remote_command.extend(['-D']) if entry: agent_command.append(entry) if kwargs.get('entry_args'): agent_command.extend(kwargs['entry_args']) rand = ''.join(random.sample('abcdefghijklmnopqrstuvwxyz0123456789', 8)) volname = 'retro-contest-tmp%s' % rand datamount = {} if kwargs.get('resultsdir'): results = os.path.realpath(kwargs['resultsdir']) datamount[convert_path(results)] = {'bind': '/root/compo/results'} os.makedirs(results, exist_ok=True) else: results = None container_kwargs = {'detach': True, 'network_disabled': True} bridge = client.volumes.create(volname, driver='local', driver_opts={ 'type': 'tmpfs', 'device': 'tmpfs' }) if kwargs.get('use_host_data'): remote_command = [ remote_command[0], '--data-dir', '/root/data', *remote_command[1:] ] datamount[convert_path(data_path())] = { 'bind': '/root/data', 'mode': 'ro' } remote = client.containers.run('openai/retro-env', remote_command, volumes={ volname: { 'bind': '/root/compo/tmp' }, **datamount }, **container_kwargs) try: agent = client.containers.run( agent_name, agent_command, volumes={volname: { 'bind': '/root/compo/tmp' }}, runtime=kwargs.get('runtime', 'nvidia'), **container_kwargs) except: remote.kill() raise a_exit = None r_exit = None if not kwargs.get('quiet'): log_thread = LogThread(agent) log_thread.start() try: while True: try: a_exit = agent.wait(timeout=5) break except requests.exceptions.RequestException: pass try: r_exit = remote.wait(timeout=5) break except requests.exceptions.RequestException: pass if a_exit is None: try: a_exit = agent.wait(timeout=1) except requests.exceptions.RequestException: agent.kill() if r_exit is None: try: r_exit = remote.wait(timeout=1) except requests.exceptions.RequestException: remote.kill() except: if a_exit is None: try: a_exit = agent.wait(timeout=0.2) except: try: agent.kill() except docker.errors.APIError: pass if r_exit is None: try: r_exit = remote.wait(timeout=0.2) except: try: remote.kill() except docker.errors.APIError: pass raise finally: if isinstance(a_exit, dict): a_exit = a_exit.get('StatusCode') if isinstance(r_exit, dict): r_exit = r_exit.get('StatusCode') if not kwargs.get('quiet'): log_thread.exit() logs = { 'remote': (r_exit, remote.logs(stdout=True, stderr=False), remote.logs(stdout=False, stderr=True)), 'agent': (a_exit, agent.logs(stdout=True, stderr=False), agent.logs(stdout=False, stderr=True)) } if results: with open(os.path.join(results, 'remote-stdout.txt'), 'w') as f: f.write(logs['remote'][1].decode('utf-8')) with open(os.path.join(results, 'remote-stderr.txt'), 'w') as f: f.write(logs['remote'][2].decode('utf-8')) with open(os.path.join(results, 'agent-stdout.txt'), 'w') as f: f.write(logs['agent'][1].decode('utf-8')) with open(os.path.join(results, 'agent-stderr.txt'), 'w') as f: f.write(logs['agent'][2].decode('utf-8')) remote.remove() agent.remove() bridge.remove() return logs
def run(game, state=None, entry=None, **kwargs): client = docker.from_env() remote_commands = [] for game, state in zip(str.split(game), str.split(state)): remote_commands.append([ 'retro-contest-remote', 'run', game, *([state] if state else []), '-b', 'results/bk2', '-m', 'results' ]) remote_name = kwargs.get('remote_env', 'openai/retro-env') num_envs = kwargs.get('num_envs', 1) agent_command = [] agent_name = kwargs.get('agent', 'agent') if kwargs.get('wallclock_limit') is not None: map(lambda x: x.extend(['-W', str(kwargs['wallclock_limit'])]), remote_commands) if kwargs.get('timestep_limit') is not None: map(lambda x: x.extend(['-T', str(kwargs['timestep_limit'])]), remote_commands) if kwargs.get('discrete_actions'): map(lambda x: x.extend(['-D']), remote_commands) if entry: agent_command.append(entry) if kwargs.get('entry_args'): agent_command.extend(kwargs['entry_args']) datamount = {} agentmount = {} if kwargs.get('resultsdir'): results = os.path.realpath(kwargs['resultsdir']) datamount[convert_path(results)] = {'bind': '/root/compo/results'} os.makedirs(results, exist_ok=True) else: results = None if kwargs.get('agentdir'): agentdir = os.path.realpath(kwargs['agentdir']) agentmount[convert_path(agentdir)] = {'bind': '/root/compo/out'} os.makedirs(agentdir, exist_ok=True) container_kwargs = {'detach': True, 'network_disabled': True} remote_kwargs = dict(container_kwargs) agent_kwargs = dict(container_kwargs) if kwargs.get('agent_shm'): agent_kwargs['shm_size'] = kwargs['agent_shm'] if kwargs.get('use_host_data'): remote_commands = list( map(lambda x: [x[0], '--data-dir', '/root/data', *x[1:]], remote_commands)) datamount[convert_path(data_path())] = { 'bind': '/root/data', 'mode': 'ro' } remotes = [] socket_vols = [] def remove_remotes(): for remote in remotes: try: remote.kill() except: pass try: remote.remove(v=True) except: pass def remove_socket_vols(): for socket_vol in socket_vols: try: socket_vol.remove() except: pass try: for i in range(num_envs): rand = ''.join( random.sample('abcdefghijklmnopqrstuvwxyz0123456789', 8)) volname = 'retro-contest-tmp%s' % rand socket_vol = client.volumes.create(volname, driver='local', driver_opts={ 'type': 'tmpfs', 'device': 'tmpfs' }) socket_vols.append(socket_vol) print("Remote command " + str(i) + " " + str(remote_commands[i])) remote = client.containers.run(remote_name, remote_commands[i], volumes={ volname: { 'bind': '/root/compo/tmp/sock' }, **datamount }, **remote_kwargs) remotes.append(remote) except: remove_socket_vols() raise try: volumes = { volume.name: { 'bind': '/root/compo/tmp/sock{0}'.format(i) } for i, volume in enumerate(socket_vols) } agent = client.containers.run(agent_name, agent_command, volumes={ **volumes, **agentmount }, runtime=kwargs.get('runtime', 'nvidia'), **agent_kwargs) except: remove_remotes() remove_socket_vols() raise a_exit = None r_exits = [None] * len(remotes) if not kwargs.get('quiet'): log_thread = LogThread(agent) log_thread.start() try: while True: try: a_exit = agent.wait(timeout=5) break except requests.exceptions.RequestException: pass found_server_error = False for i, remote in enumerate(remotes): try: r_exits[i] = remote.wait(timeout=5) found_server_error = True except requests.exceptions.RequestException: pass if found_server_error: break if a_exit is None: try: a_exit = agent.wait(timeout=10) except requests.exceptions.RequestException: agent.kill() for i, (r_exit, remote) in enumerate(zip(r_exits, remotes)): if r_exit is None: try: r_exits[i] = remote.wait(timeout=10) except requests.exceptions.RequestException: remote.kill() except: if a_exit is None: try: a_exit = agent.wait(timeout=1) except: try: agent.kill() except docker.errors.APIError: pass for i, (r_exit, remote) in enumerate(zip(r_exits, remotes)): if r_exit is None: try: r_exits[i] = remote.wait(timeout=1) except: try: remote.kill() except docker.errors.APIError: pass raise finally: if isinstance(a_exit, dict): a_exit = a_exit.get('StatusCode') for i, r_exit in enumerate(r_exits): if isinstance(r_exit, dict): r_exits[i] = r_exit.get('StatusCode') if not kwargs.get('quiet'): log_thread.exit() remote_logs = { 'remote{0}'.format(i): (r_exit, remote.logs(stdout=True, stderr=False), remote.logs(stdout=False, stderr=True)) for i, (r_exit, remote) in enumerate(zip(r_exits, remotes)) } logs = { **remote_logs, 'agent': (a_exit, agent.logs(stdout=True, stderr=False), agent.logs(stdout=False, stderr=True)) } if results: for i in range(len(remotes)): with open( os.path.join(results, 'remote{0}-stdout.txt'.format(i)), 'w') as f: f.write(logs['remote{0}'.format(i)][1].decode('utf-8')) with open( os.path.join(results, 'remote{0}-stderr.txt'.format(i)), 'w') as f: f.write(logs['remote{0}'.format(i)][2].decode('utf-8')) with open(os.path.join(results, 'agent-stdout.txt'), 'w') as f: f.write(logs['agent'][1].decode('utf-8')) with open(os.path.join(results, 'agent-stderr.txt'), 'w') as f: f.write(logs['agent'][2].decode('utf-8')) remove_remotes() agent.remove(v=True) remove_socket_vols() return logs
def main(argv=sys.argv[1:]): parser = argparse.ArgumentParser( description= 'Run support code for OpenAI Retro Contest remote environment') parser.set_defaults(func=lambda args: parser.print_help()) parser.add_argument( '--data-dir', type=str, help='Use a custom data directory (must be named `data`)') subparsers = parser.add_subparsers() parser_run = subparsers.add_parser('run', description='Run Remote environment') parser_list = subparsers.add_parser( 'list', description='List information about environments') parser_run.set_defaults(func=run_args) parser_run.add_argument('game', type=str, help='Name of the game to run') parser_run.add_argument('state', type=str, default=retro.STATE_DEFAULT, nargs='?', help='Name of initial state') parser_run.add_argument('--monitordir', '-m', type=str, help='Directory to hold monitor files') parser_run.add_argument('--bk2dir', '-b', type=str, help='Directory to hold BK2 movies') parser_run.add_argument('--daemonize', '-d', action='store_true', default=False, help='Daemonize (background) the process') parser_run.add_argument('--wallclock-limit', '-W', type=float, default=None, help='Maximum time to run in seconds') parser_run.add_argument('--timestep-limit', '-T', type=int, default=None, help='Maximum time to run in timesteps') parser_run.add_argument('--discrete-actions', '-D', action='store_true', help='Use a discrete action space') parser_list.set_defaults(func=lambda args: parser_list.print_help()) subparsers_list = parser_list.add_subparsers() parser_list_games = subparsers_list.add_parser('games', description='List games') parser_list_games.set_defaults(func=list_games) parser_list_games.add_argument('--system', '-s', type=str, help='List for a specific system only') parser_list_states = subparsers_list.add_parser('states', description='List') parser_list_states.set_defaults(func=list_states) parser_list_states.add_argument('game', type=str, default=None, nargs='*', help='List for specified games only') args = parser.parse_args(argv) if args.data_dir: retro.data_path(args.data_dir) args.func(args)
# numeric import numpy as np import pandas as pd import logging import gym import retro import retro.data from retro_contest.local import make import retro_contest from . import wrappers from .data import train_states, validation_states # INIT ROM_DIRS = ['./roms', retro.data_path()] logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__file__) logger.setLevel(logging.INFO) def roms_import_paths(paths): """Import sega roms from a list of paths""" potential_roms = [] for path in paths: for base, _, files in os.walk(path): potential_roms.extend([os.path.join(base, file) for file in files]) print('Importing %i potential games...' % len(potential_roms)) retro.data.merge(*potential_roms, quiet=False)