주요 컨텐츠로 이동

Databricks의 TensorFlow™

Illustration

GPU 사용

GPU(그래픽 처리 장치)는 3D 그래픽에 필요한 계산을 수행하도록 설계된 대부분의 최신 컴퓨터의 구성 요소입니다. 가장 일반적인 용도는 비디오 게임에 이러한 작업을 수행하여 사용자에게 게임을 보여주기 위해 다각형이 이동하는 위치를 계산하는 것입니다. GPU는 기본적으로 고도로 병렬화된 계산을 수행하는 여러 작은 프로세서로 구성된 대규모 어레이입니다. 기본적으로 지금 미니 슈퍼 컴퓨터*가 실행되고 있는 것입니다.

GPU의 각 'CPU'는 매우 느리지만 그 수가 많고 수치 처리에 특화되어 있습니다. 이는 GPU가 간단한 수치 처리 작업을 동시에 대규모로 수행할 수 있음을 의미합니다. 다행히 이것이 바로 많은 머신 러닝이 수행해야 하는 작업입니다.

GPU가 없으신가요?

지난 10년 동안 최신 컴퓨터에는 어떤 형태로든 GPU가 탑재되었는데, 마더보드에 내장된 경우도 있습니다. 이 튜토리얼에서는 이것으로 충분합니다.

사용 중인 그래픽 카드의 유형을 알아야 합니다. Windows 사용자는 이 지침을 따르면 되지만, 다른 시스템 사용자는 해당 시스템의 설명서를 참조해야 합니다.

비Nvidia 그래픽 카드 사용자

다른 그래픽 카드도 지원될 수 있지만 이 튜토리얼은 최신 NVidia 그래픽 카드에서만 테스트됩니다. 그래픽 카드가 다른 유형인 경우 학습을 위해 NVidia 그래픽 카드를 찾아 구입하거나 대여하는 것이 좋습니다. 구입이나 대여가 어려운 경우 현지 대학교나 학교에 연락하여 도움을 받을 수 있는지 알아봅니다. 그래도 문제가 해결되지 않으면 참고하고 표준 CPU에서 작업하시기 바랍니다. 학습은 추후 마이그레이션할 수 있습니다.

* 참고: 실제로 슈퍼 컴퓨터는 아니지만 여러 면에서 다소 유사합니다.

GPU 지원 TensorFlow 설치

GPU 지원 TensorFlow를 아직 설치하지 않았다면 먼저 설치해야 합니다. 단원 1의 지침에는 언급되어 있지 않으므로 GPU 지원을 활성화하기 위해 노력하지 않았습니다.

이전 환경을 업데이트하기보다 새로운 Anaconda 환경을 구축하는 것이 좋습니다.

시작하기 전에

공식 TensorFlow 설치 지침으로 이동하여 Anaconda 설치 지침을 따릅니다. 이 지침과 단원 1에서 수행한 것의 주요 차이점은 시스템에 GPU 지원 TensorFlow 버전이 필요하다는 것입니다. 그러나 이 환경에 TensorFlow를 설치하기 전에 CUDA 및 CuDNN을 사용하여 GPU를 지원하도록 컴퓨터를 설정해야 합니다. 공식 TensorFlow 문서에서 이 설정 방법을 단계별로 안내하지만, 최신 Ubuntu 설치를 설정하려는 경우 이 튜토리얼을 따르는 것이 좋습니다. 주된 이유는 이 튜토리얼의 작성 시점(2016년 7월)을 기준으로, CUDA가 아직 최신 Ubuntu 버전에 빌드되지 않았기 때문입니다. 즉, 프로세스에 수작업이 많이 필요합니다.

개인 GPU 사용

최소한 구문적 측면에서는 매우 간단합니다. 다음을 바꾸기만 하면 됩니다.

 

# Setup operations

with tf.Session() as sess:
    # Run your code

 

변경 후:

 

with tf.device("/gpu:0"):
    # Setup operations

with tf.Session() as sess:
    # Run your code

 

이 새 줄은 새로운 컨텍스트 관리자를 만들어 TensorFlow에 GPU에서 해당 작업을 수행하도록 지시합니다.

구체적인 예를 살펴보겠습니다. 아래의 코드는 명령줄에 특정 크기의 임의 행렬을 만듭니다. 명령줄 옵션을 사용하여 CPU 또는 GPU에서 코드를 실행할 수 있습니다.

 

import sys
import numpy as np
import tensorflow as tf
from datetime import datetime

device_name = sys.argv[1]  # Choose device from cmd line. Options: gpu or cpu
shape = (int(sys.argv[2]), int(sys.argv[2]))
if device_name == "gpu":
    device_name = "/gpu:0"
else:
    device_name = "/cpu:0"

with tf.device(device_name):
    random_matrix = tf.random_uniform(shape=shape, minval=0, maxval=1)
    dot_operation = tf.matmul(random_matrix, tf.transpose(random_matrix))
    sum_operation = tf.reduce_sum(dot_operation)


startTime = datetime.now()
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as session:
        result = session.run(sum_operation)
        print(result)

# It can be hard to see the results on the terminal with lots of output -- add some newlines to improve readability.
print("\n" * 5)
print("Shape:", shape, "Device:", device_name)
print("Time taken:", datetime.now() - startTime)

print("\n" * 5)

 

명령줄에서 다음과 같이 실행할 수 있습니다.

python matmul.py gpu 1500

여기에서는 크기가 1500 제곱인 행렬의 CPU를 사용합니다. 다음을 사용하여 CPU에서도 동일한 작업을 수행합니다.

python matmul.py cpu 1500

GPU 지원 코드를 실행할 때 가장 먼저 알아차릴 수 있는 것은 일반 TensorFlow 스크립트에 비해 출력이 크게 증가한다는 것입니다. 다음은 연산 결과를 출력하기 전에 컴퓨터에서 출력하는 내용입니다.

 

I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcudnn.so.5 locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcurand.so locally
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:925] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
I tensorflow/core/common_runtime/gpu/gpu_init.cc:102] Found device 0 with properties: 
name: GeForce GTX 950M
major: 5 minor: 0 memoryClockRate (GHz) 1.124
pciBusID 0000:01:00.0
Total memory: 3.95GiB
Free memory: 3.50GiB
I tensorflow/core/common_runtime/gpu/gpu_init.cc:126] DMA: 0 
I tensorflow/core/common_runtime/gpu/gpu_init.cc:136] 0:   Y 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:838] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 950M, pci bus id: 0000:01:00.0)

 

코드가 이와 유사한 출력을 생성하지 않는다면 GPU 지원 Tensorflow를 실행하고 있지 않은 것입니다. 또는 ImportError: libcudart.so.7.5: cannot open shared object file: No such file or directory와 같은 오류가 발생하면 CUDA 라이브러리가 제대로 설치되지 않은 것입니다 이 경우 다시 돌아가 시스템에 CUDA를 설치하기 위한 지침을 따라야 합니다.

위 코드를 CPU와 GPU 모두에서 실행하면서 숫자를 천천히 늘려봅니다. 1500으로 시작한 다음 3000, 4500 등을 시도합니다. CPU는 시간이 꽤 오래 걸리는 반면 GPU는 이 연산을 매우 빠르게 처리함을 알 수 있습니다.

GPU가 여러 개인 경우 둘 중 하나를 사용할 수 있습니다. GPU는 0으로 인덱싱됩니다. 위의 코드는 첫 번째 GPU에 액세스합니다. 장치를 gpu:1로 변경하면 두 번째 GPU가 사용됩니다. 그 후에도 동일한 규칙이 사용됩니다. 계산을 여러 GPU로 분산할 수도 있습니다. 또한 유사한 방식으로 머신의 CPU에 액세스할 수 있는데, cpu:0(또는 다른 숫자)을 사용하면 됩니다.

GPU로 전송해야 하는 연산 유형

일반적으로 프로세스의 단계를 '이 수학 연산을 수천 번 수행' 등과 같이 설명할 수 있으면 GPU로 전송합니다. 예를 들면 행렬 곱셈과 역행렬 계산이 있습니다. 실제로 많은 기본 행렬 연산이 GPU에 가장 많이 사용됩니다. 지나치게 광범위하고 단순한 규칙이 아닌 경우는 CPU에서 수행되어야 합니다.

장치를 변경하고 GPU를 사용하는 데에도 비용이 발생합니다. GPU는 컴퓨터의 나머지 부분에 직접 액세스할 수 없습니다(물론 디스플레이는 제외). 따라서 GPU에서 명령을 실행하는 경우 먼저 모든 데이터를 GPU에 복사한 다음 연산을 수행하고 결과를 컴퓨터의 기본 메모리에 다시 복사해야 합니다. TensorFlow는 이를 내부적으로 처리하므로 코드는 간단하지만 여전히 연산을 수행해야 합니다.

GPU에서 모든 연산을 수행할 수 있는 것은 아닙니다. 다음 오류가 발생하면 CPU에서 처리할 수 없는 연산을 수행하려고 하는 것입니다.

 

Cannot assign a device to node 'PyFunc': Could not satisfy explicit device specification '/device:GPU:1' because no devices matching that specification are registered in this process;

 

이 경우 장치를 이 연산을 처리할 CPU로 수동 변경하거나 장치를 자동으로 변경하도록 TensorFlow를 설정할 수 있습니다. 그러려면 세션 생성의 일부로 수행된 구성에서 allow_soft_placement를 True로 설정합니다. 프로토타입은 다음과 같습니다.

 

with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)):
    # Run your graph here

 

또한 GPU를 사용할 때 장치 배치를 기록해두면 다양한 장치 사용과 관련된 문제를 쉽게 디버깅할 수 있습니다. 그러면 장치 사용량이 로그에 출력되어 장치가 변경되는 시점과 이 시점이 그래프에 미치는 영향을 확인할 수 있습니다.

 

with tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)):
    # Run your graph here

 

  1. TensorFlow용 GPU를 사용하도록 컴퓨터를 설정합니다. (또는 최신 GPU가 없으면 대여할 컴퓨터를 찾습니다.)
  2. GPU에서 이전 실습 솔루션을 실행해 봅니다. GPU에서 수행할 수 있는 연산과 수행할 수 없는 연산을 확인합니다.
  3. GPU와 CPU 모두에서 연산을 사용하는 프로그램을 빌드합니다. 단원 5에서 살펴본 프로파일링 코드를 사용하여 GPU로 데이터를 보내고 GPU에서 데이터를 검색할 때의 영향을 예측합니다.
  4. 코드를 보내주세요! 여러분의 코드 예시, Tensorflow 사용 방법, 발견한 유용한 정보를 공유해 주세요.