DeepLearning/Learning TensorFlow

[러닝 텐서플로]Chap09 - 분산 텐서플로

Excelsior-JH 2018. 7. 4. 22:40

Chap09 - 분산 텐서플로

9.1 분산 컴퓨팅

텐서플로에서의 분산 컴퓨팅은 딥러닝 모델의 학습 속도를 향상 시키기 위해서 여러 대의 기계를 사용하는 것을 말한다.

9.2 텐서플로의 병렬처리 요소

그렇다면, 텐서플로에서 병렬계산(parallel computation)에 사용되는 요소와 개념에 대해 알아보도록 하자.

9.2.1 tf.app.flags

tf.app.flags는 병렬계산과는 전혀 상관이 없지만, 텐서플로 예제에서 많이 사용되므로 아는것이 좋다. 그리고 이 교재의 마지막 예제에서도 tf.app.flags를 사용한다.

tf.app.flags는 Python의 argparse 모듈의 래퍼(wrapper)이다. argparse모듈은 Terminal이사 cmd창에서의 python ~.py --~~에 있는 인자를 처리하는데 사용된다.

예를 들어 아래와 같은 Python 명령을 입력한다고 가정한다면, distribute.py 프로그램에 전달되는 인자는 다음과 같다.

  python distribute_mnist_cnn.py --job_name="ps" --task_index=0

##전달되는 인자
job_name="ps"
task_index=0

이러한 명령을 통해 다음과 같이 파이썬 스크립트 안에서 이 정보를 추출할 수 있다.

  tf.app.flags.DEFINE_string("job_name", "", "name of job")
tf.app.flags.DEFINE_integer("task_index", 0, "Index of task")

tf.app.flags에는 다음과 같은 유형들이 있다.

  • tf.app.flags.DEFINE_string: 스트링 값을 정의

  • tf.app.flags.DEFINE_boolean: 참거짓 값을 정의

  • tf.app.flags.DEFINE_float: 부동소수점 값을 정의

  • tf.app.flags.DEFINE_integer: 정수를 정의

tf.app.flags.FLAGS는 명령에서 입력되어 파싱된 모든 인수의 값을 포함하며, FLAGS.arg로 접근할 수 있다.

9.2.2 클러스터와 서버

텐서플로의 클러스터(cluster)는 연산 그래프의 병렬처리에 참여하는 노드(또는 태스크)의 집합이다. 각 태스크는 다음과 같이 접근할 수 있는 네트워크 주소로 정의한다.

  parameter_servers = ['hostname1:port']  # ex. localhost:2222
workers = ['hostname2:port',  # ex. 192.168.0.3:2223
          'hostname3:port',
          'hostname4:port']
cluster = tf.train.ClusterSpec({
   'parameter_server': parameter_servers,
   'worker': workers
})

위의 예제코드에서 태스크는 하나의 매개변수 서버(parameter server)와 세 개의 워커(worker)로 구성되어 있으며, 매개변수 서버와 워커의 역할은 잡(job)이라고 부른다.

각 태스크는 텐서플로 서버를 실행하며, 계산을 위해 자원을 사용하고 병렬처리를 효율적으로 하도록 클러스터 내의 다른 태스크와 통신한다.

hostname2:port인 워커 노드에 클러스터를 정의하는 방법은 다음과 같다.

  server = tf.train.Server(cluster,
                        job_name='worker',
                        task_index=0)

위에서 처럼 클러스터와 서버를 정의를 해준 다음, 병렬 계산을 수행할 수 있는 연산 그래프를 작성해야 한다.

9.2.3 디바이스 간 연산 그래프 복제

그래프 간 복제(between-graph replication) 는 동일한 연산 그래프가 각 워크 태스크상에 개별적으로 구성되어있는 병렬화 방법이다. 학슥 단계에서의 기울기(gradient) 값은 각 워커(worker)에 계산되고 매개변수 서버에 의해 결합된다.

tf.train.replica_device_setter()를 이용해 각 태스크에 연산 그래프(모델)을 복제할 수 있다. worker_device 인자에 클러스터의 태스크를 설정해준다.

  with tf.device(tf.train.replica_device_setter(
       worker_device="/job:worker/task:%d" % 0,
       cluster=cluster)
   # build model...

매개변수 서버에는 연산 그래프(모델)를 작성하지 않으며, 대신 프로세스가 종료되지 않도록 server.join()으로 병렬 계산이 수행되는 동안 매개변수 서버가 종료되지 않도록 해준다.

9.2.4 관리 세션

tf.train.Supervisor()는 학습을 관리해주고 병렬 환경을 설정하는데 필요한 기능을 제공한다.

  sv = tf.train.Supervisor(is_chief=True,
                        logdir=None,
                        global_step=...,
                        init_op=...)
  • is_chief(bool): If True, create a chief supervisor in charge of initializing and restoring the model.

  • logdir(string): A string. Optional path to a directory where to checkpoint the model and log events for the visualizer. 로그를 저장할 경로.

  • global_step: An integer Tensor of size 1 that counts steps. 전역 step의 값

  • init_op: Used by chief supervisors to initialize the model when it can not be recovered. ex. tf.global_variables_initializer()

세션은 Supervisormanaged_session으로 설정한다.

  with sv.managed_session(server.target) as sess:
   # Training

9.2.5 디바이스 배치

텐서플로의 디바이스 배치(device placement) 는 CPU 또는 GPU(가 있는경우)에 연산 그래프의 연산이 실행되는 위치를 지정해주는 것을 말한다. 기본적으로 텐서플로는 사용 가능한 모든 CPU를 사용한다.

텐서플로는 tf.ConfigProto(log_device_placement=True)를 통해 연산 그래프가 어떤 디바이스에 배치되었는지 확인할 수 있다. 아래의 예제코드는 연산 그래프가 어떤 디바이스에 배치되었는지 확인하는 코드이다.



  2018-07-04 15:41:48.549266: I T:\src\github\tensorflow\tensorflow\core\common_runtime\direct_session.cc:284] Device mapping:

MatMul: (MatMul): /job:localhost/replica:0/task:0/device:CPU:0
2018-07-04 15:41:48.553920: I T:\src\github\tensorflow\tensorflow\core\common_runtime\placer.cc:886] MatMul: (MatMul)/job:localhost/replica:0/task:0/device:CPU:0
Const_1: (Const): /job:localhost/replica:0/task:0/device:CPU:0
2018-07-04 15:41:48.559578: I T:\src\github\tensorflow\tensorflow\core\common_runtime\placer.cc:886] Const_1: (Const)/job:localhost/replica:0/task:0/device:CPU:0
Const: (Const): /job:localhost/replica:0/task:0/device:CPU:0
2018-07-04 15:41:48.567907: I T:\src\github\tensorflow\tensorflow\core\common_runtime\placer.cc:886] Const: (Const)/job:localhost/replica:0/task:0/device:CPU:0
[[ 5. 8.]
[13. 20.]]

디바이스를 명시적으로 지정해주는 방법은 아래(첫 번째 GPU에 지정)와 같다.

  with tf.device('/gpu:0'):
   op = ...

클러스터에서의 배치는 특정 태스크를 지정해줘야 한다.

  with tf.device('/job:worker/task:0'):  # 첫번째 워커 태스크에 배치
   op = ...

9.3 MNIST CNN 모델을 분산 학습 시키기

이제 앞에서 살펴본 분산 컴퓨팅 방법을 적용해 MNIST 데이터를 분류하는 CNN 모델을 분산 학습을 시켜보도록 하자.

전체 코드는 아래와 같다.


위의 코드를 실행하기 위해서는 아래의 distribute_mnist_cnn-run.py 파일을 새로운 Terminal에서 실행하면 된다.


위의 distribute_mnist_cnn-run.py 파일을 실행시키면 각 워커 별의 정확도를 확인할 수 있다.

  Worker : 1, Step: 4400.0, Accuracy (batch): 0.9800000190734863
Worker : 2, Step: 4500.0, Accuracy (batch): 0.9800000190734863
Worker : 0, Step: 4500.0, Accuracy (batch): 1.0
Worker : 2, Step: 4600.0, Accuracy (batch): 0.9800000190734863
Worker : 0, Step: 4600.0, Accuracy (batch): 1.0
Worker : 0, Step: 4800.0, Accuracy (batch): 1.0
Worker : 2, Step: 4900.0, Accuracy (batch): 1.0
Test-Accuracy: 0.9871000051498413