Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
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)