multiprocessing에서 gym이 오작동하는 경우

tl;dr

  • gym>=0.10.6이면 상관x
  • multiprocessing으로 학습을 진행시키는 경우 주의

impala랑 popart-impala를 구현하다가 소스 코드엔 문제가 없는것 같은데,
도저히 Pong평균스코어가 18점을 못넘기길래 gym을 업데이트 해봤더니
잘되길래 gym 버그인줄 알았는데 결국 내 코드가 문제였다(gym도 쪼끔 잘못했다.)


atari 옵션 설명

gym/envs/__init__.py
우선 gym에서 사용되는 atari게임들의 옵션을 두 부분으로 나눠서
설명할 수 있는데,

  • Deterministic: 4프레임 마다 건너뜀(frameskip), 4 프레임동안 같은 action 반복
  • NoFrameskip: frameskip 없음
  • 없음: {2,3,4}중에 uniform하게 선택해서 건너뜀

  • v0: 25% 확률로 주어진 행동 무시하고 이전 행동 반복
  • v4: 무시안함

그래서 PongDeterministic-v4라고 하면 4프레임 마다 건너뛰고, 행동을 무시하지 않는 환경을 얻을 수 있다.

문제

우선 사용하던 gym이 0.10.5였고 최신 버전이 현재 0.14.0인데,
같은 PongDeterministic-v4라도 결과가 다르길래
어느 버전부터 이렇게 잘못되나 확인해 봤다.

알고리즘은 popart-impala, worker수는 16
시간별로 전체 worker의 값을 평균냈다.

fig3

0.10.6부턴 제대로 작동하길래
각이 나온거 같아서 gym github의 소스코드를 빼봤더니

gym github 0.10.5/0.10.6 비교
atari관련 된건 gym/envs/atari/atari_env.py 밖에 안보였고 해당부분은 0.14.0의 코드에선 이렇게 되어있다.

utils.EzPickle.__init__(
        self,
        game,
        mode,
        difficulty,
        obs_type,
        frameskip,
        repeat_action_probability)

0.10.5 이전에선 frameskip, repeat_action_probability가 없고 obs_type까지만 있다.
저 두 argument를 넘기느냐 안넘기느냐 차이인것 같아,
두줄을 지운거랑 안지운거랑 돌려봤다.

fig1

  • 위: 한 에피소드당 스텝 수 평균

fig2

  • 아래: 에피소드 Reward평균

아무래도 이게 확실히 원인인것 같다.

진짜 원인

impala를 설계할때 multi-thread가 아니라 multi-processing으로 설계했는데
fork된 뒤로 독립적인 프로세스란 사실을 까먹은게 문제였다.

class Agent(multiprocessing.Process):
    def __init__(self):
        env = gym.make("PongNoFrameskip-v4")
        print("a: ",env.frameskip)

    def run(self):
        print("b: ",env.frameskip)

agent = Agent()
agent.start()

이렇게 하면,

a: 4
b: 4

가 나올 것 같지만, 0.10.5 이전버전에선

a: 4
b: (2,5) <-이건 atari기본 설정

이렇게 나와버린다.

multi-process가 시작되면서 fork했던 env가 아니라, 새로 오브젝트를 생성하는 문제인것 같다.

0.10.5까지는 init할때 frameskip, repeat_action_probability를 넘겨주지 않았기 때문에, 그게 없는 채로 오브젝트가 생성된 것이고,

0.10.6부터는 넘겨주기 때문에 잘 작동하는 것 같다.

근데 관련해서 생각하다 보니까 init에서 env생성하면 다른 process가 생성될때 같이 fork된단 얘긴데,

그러면 메모리 낭비인것 같아서 run함수 안에서 그냥 생성하는 코드로 바꿨더니 초기 실행이 더 빨라졌다.

예상치 못한 수확도 건져서 이득봤다.

reference

  1. https://github.com/openai/gym/issues/1496
  2. https://github.com/openai/gym/compare/c8f8149..5cbc105
  3. https://github.com/openai/gym/issues/349
  4. https://github.com/openai/gym/blob/master/gym/envs/__init__.py