Microsoft MVP성태의 닷넷 이야기
스크립트: 24. 파이썬 - tensorflow 2.6 NVidia GPU 사용 방법 [링크 복사], [링크+제목 복사]
조회: 15077
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 3개 있습니다.)

파이썬 - tensorflow 2.6 NVidia GPU 사용 방법

tensorflow 모듈 설치 후,

c:\temp> pip install tensorflow
...[생략]...
Successfully installed gast-0.4.0 grpcio-1.39.0 h5py-3.1.0 tensorflow-2.6.0 tensorflow-estimator-2.6.0

다음과 같이 import만 해도,

import tensorflow as tf

이런 경고가 발생할 수 있습니다.

2021-08-22 18:34:05.288193: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'cudart64_110.dll'; dlerror: cudart64_110.dll not found
2021-08-22 18:34:05.288405: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.

그런 경우, 최신 CUDA Toolkit을 설치해 줍니다.

CUDA Toolkit Download
; https://developer.nvidia.com/cuda-toolkit

이후에는 다음과 같이 코딩을 해도 일단 오류가 발생하지 않습니다.

import tensorflow as tf

print(tf.__version__)  # 출력 결과: 2.6.0
print(tf.version.VERSION)  # 2.6.0
print(tf.version.GIT_VERSION)  # v2.6.0-rc2-32-g919f693420e
print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))  # Num GPUs Available:  1

그런데, 다음의 코드를 추가해 실행하면,

print(tf.config.list_physical_devices('GPU'))

이런 오류가 발생합니다.

2021-08-22 21:47:53.395396: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'cudnn64_8.dll'; dlerror: cudnn64_8.dll not found
2021-08-22 21:47:53.395617: W tensorflow/core/common_runtime/gpu/gpu_device.cc:1835] Cannot dlopen some GPU libraries. Please make sure the missing libraries mentioned above are installed properly if you would like to use GPU. Follow the guide at https://www.tensorflow.org/install/gpu for how to download and setup the required libraries for your platform.
Skipping registering GPU devices...

링크(https://www.tensorflow.org/install/gpu)에 보면, "Software requirements"로 다음의 항목들이 나옵니다.

  • NVIDIA® GPU drivers - CUDA® 11.2 requires 450.80.02 or higher.
  • CUDA® Toolkit - TensorFlow supports CUDA® 11.2 (TensorFlow >= 2.5.0)
  • CUPTI ships with the CUDA® Toolkit.
  • cuDNN SDK 8.1.0 cuDNN versions).
  • (Optional) TensorRT 6.0 to improve latency and throughput for inference on some models.

아하... "cuDNN SDK 8.1.0 cuDNN versions" 항목은 별도로 설치가 필요한 거군요. 따라서, 다음의 경로에서 최신 버전을 다운로드합니다.

cuDNN Download
; https://developer.nvidia.com/cudnn

참고로, 다운로드할 항목의 이름이 "cuDNN Library for Windows (x86)"라는 식으로 "(x64)"가 아니라 "(x86)"으로 명시돼 있는데, 그냥 인텔 아키텍처에 대한 통칭으로서 x86을 표기한 듯합니다. 따라서 그냥 받아 보면 파일명이 "cudnn-11.4-windows-x64-v8.2.2.26.zip"라고 되어 있으므로 64비트가 맞습니다.

그런데 문제는 zip 파일이라 어디다 설치해야 할지를 알 수가 없습니다. 물론 PATH 환경 변수에 걸어두면 되겠는데요, 그래도 아래의 글을 보니,

How to Install the NVIDIA CUDA Driver, CUDA Toolkit, CuDNN, and TensorRT on Windows
; https://levelup.gitconnected.com/how-to-install-the-nvidia-cuda-driver-cuda-toolkit-cudnn-and-tensorrt-on-windows-af58647b6d9a#078b

그냥 CUDA Toolkit이 설치된 디렉터리의 bin으로 복사하라고 합니다. 보니까, 실제로 .\cudnn-11.4-windows-x64-v8.2.2.26\cuda 디렉터리 하위의 bin, include, lib에 있는 파일들이 "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.4" 디렉터리 하위의 내용과 겹치지 않기 때문에 충돌 걱정 없이 그대로 복사해도 됩니다.

끝이군요. ^^ 이제 다시 Python 스크립트를 실행하면 다음과 같은 결과를 확인할 수 있습니다.

import tensorflow as tf

print(tf.__version__)  # 출력 결과: 2.6.0
print(tf.config.list_physical_devices('GPU'))  # 출력 결과: [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

혹은 더 자세한 정보를 원한다면 이렇게 해 주시고.

from tensorflow.python.client import device_lib

print(device_lib.list_local_devices())

""" 출력 결과
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 16660298716077284787
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 6966018048
locality {
  bus_id: 1
  links {
  }
}
incarnation: 12004974687831180911
physical_device_desc: "device: 0, name: NVIDIA GeForce GTX 1070, pci bus id: 0000:01:00.0, compute capability: 6.1"
]
"""




예제를 하나 가져와 볼까요? ^^

딥 러닝 입문
; https://e-koreatech.step.or.kr/page/lms/?m1=course&course_id=170363&m2=course_detail

위의 강좌에 있는 파이썬 예제 코드를,

import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation
import random
import numpy as np
import os

data_cnt = 100
random.seed(0)  #테스트를 위해!

x_data = []
for i in range(data_cnt):
    x_data.append([random.randint(7, 20), random.randint(80, 130)])
    x_data.append([random.randint(1, 10), random.randint(50, 100)])

y_data = []
for i in range(data_cnt):
    y_data.append(1)
    y_data.append(0)

X_train = np.array(x_data)
Y_train = np.array(y_data)

model = Sequential()
model.add(Dense(20, input_dim=2, activation='relu'))
model.add(Dense(10,activation='relu'))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

now = datetime.datetime.now()
hist = model.fit(X_train, Y_train, epochs=200, batch_size=10, validation_data=(X_train, Y_train))
print('elapsed: ', datetime.datetime.now() - now)

# 모델 평가 및 분석

x_data = []
for i in range(10):
    x_data.append([random.randint(7, 20), random.randint(80, 130)])
    x_data.append([random.randint(1, 10), random.randint(50, 100)])

y_data = []
for i in range(10):
    y_data.append(1)
    y_data.append(0)

X_test = np.array(x_data)
Y_test = np.array(y_data)

loss_and_metrics = model.evaluate(X_test, Y_test, batch_size=1)

print('')
print('loss:', str(loss_and_metrics[0]))
print('accuracy', str(loss_and_metrics[1]))

fig, loss_ax = plt.subplots()
acc_ax = loss_ax.twinx()

loss_ax.plot(hist.history['loss'], 'y', label='train_loss')
loss_ax.plot(hist.history['val_loss'], 'r', label='val loss')

acc_ax.plot(hist.history['accuracy'], 'b', label='train acc')
acc_ax.plot(hist.history['val_accuracy'], 'g', label='val acc')

loss_ax.set_xlabel('epoch')
loss_ax.set_ylabel('loss')
acc_ax.set_ylabel('accuracy')

loss_ax.legend(loc='upper left')
acc_ax.legend(loc='lower left')

plt.show()

실행해 보면, 다음과 같은 결과를 얻게 됩니다.

Num GPUs Available:  1
2021-08-29 16:59:31.204079: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-08-29 16:59:31.824942: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 6643 MB memory:  -> device: 0, name: NVIDIA GeForce GTX 1070, pci bus id: 0000:01:00.0, compute capability: 6.1
2021-08-29 16:59:32.157767: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:185] None of the MLIR Optimization Passes are enabled (registered 2)
...[생략]...
Epoch 91/200
20/20 [==============================] - 0s 6ms/step - loss: 0.4118 - accuracy: 0.7800 - val_loss: 0.4032 - val_accuracy: 0.7600
Epoch 92/200
20/20 [==============================] - 0s 7ms/step - loss: 0.4047 - accuracy: 0.7700 - val_loss: 0.4038 - val_accuracy: 0.7550
Epoch 93/200
20/20 [==============================] - 0s 6ms/step - loss: 0.4028 - accuracy: 0.7500 - val_loss: 0.4045 - val_accuracy: 0.7700

elapsed:  0:00:26.272990 // i5-4670 CPU인 경우

이때의 CPU와 GPU 자원 소비 상황을 보면 이렇습니다.

tensorflow_gpu_nvidia_1.png

GPU의 경우 "Dedicated GPU memory usage"는 거의 최대로 올라가는 반면 GPU 자체의 "Utilization"은 높지 않습니다. 반면, 여전히 CPU 사용량은 높은데요, 사실 이게 GPU 연산이 된 것인지조차 의심스럽습니다. ^^;

게다가 출력 정보에 보면 "This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX AVX2"라는 메시지가 나오는데요, 검색해 보면 저 옵션을 넣고 재빌드를 해야 한다고 합니다. 아마도 저 옵션의 tensorflow 빌드라면 CPU 사용량이 더 낮거나, 아니면 좀 더 빠른 시간에 끝나지 않을까... 예상을 해봅니다.

참고로, "This TensorFlow binary is ..." 정보 메시지가 귀찮을 수 있는데요, 어차피 새로 빌드를 하지 않는다면 계속 봐야 하므로 그냥 옵션을 통해 꺼 두시는 것이 좋습니다. 방법은 사용 전에, 다음과 같은 환경 변수를 추가하면 됩니다.

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'




재미있는 건, GPU 사용을 비활성화시키면,

os.environ["CUDA_VISIBLE_DEVICES"] = "-1"

학습 시간이 "elapsed: 0:00:09.787607"로 나와 오히려 3배 정도 빠른 성능을 보였습니다. 그러니까, 아마도 "CUDA로 작성한 RGB2RGBA 성능" 글에 쓴 것처럼 GPU 메모리 복사 시간에 따른 오버헤드가 더 큰 것으로 보입니다. 따라서 GPU 사용에 대한 이득을 보려면 kernel 함수에 해당하는 코드가 충분한 연산 코드를 담고 있어야 하는 것입니다.

이를 테스트하기 위해 "딥 러닝 입문" 강의에 나온 MNIST 예제를,

from datetime import datetime

from tensorflow.keras.datasets import mnist
from tensorflow.keras import utils
from tensorflow.keras.layers import Dense
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
import os

# CPU 사용으로 테스트하려면 주석 제거
# os.environ["CUDA_VISIBLE_DEVICES"] = "-1"

(X_train, Y_train), (X_test, Y_test) = mnist.load_data()

X_train, X_test = X_train/255.0, X_test/255.0

number_of_data = len(X_train)
train_count = 50000
val_count = 10000

X_val = X_train[number_of_data - val_count:]
Y_val = Y_train[number_of_data - val_count:]
X_train = X_train[:train_count]
Y_train = Y_train[:train_count]

# mnist dataset: width 28 x height 28

X_train = X_train.reshape(train_count, 784).astype('float32')
X_val = X_val.reshape(val_count, 784).astype('float32')
X_test = X_test.reshape(10000, 784).astype('float32')

Y_train = utils.to_categorical(Y_train, 10)
Y_val = utils.to_categorical(Y_val, 10)
Y_test = utils.to_categorical(Y_test, 10)

model = Sequential()

model.add(Dense(units=512, input_dim=28*28, activation='relu'))
model.add(Dense(units=256, activation='relu'))
model.add(Dense(units=128, activation='relu'))
model.add(Dense(units=64, activation='relu'))
model.add(Dense(units=32, activation='relu'))
model.add(Dense(units=10, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

now = datetime.now()
hist = model.fit(X_train, Y_train, epochs=20, batch_size=50, validation_data=(X_val, Y_val))
print('elapsed: ', datetime.now() - now)

loss_and_metrics = model.evaluate(X_test, Y_test, batch_size=32)
print('')
print('loss: ', str(loss_and_metrics[0]))
print('accuracy: ', str(loss_and_metrics[1]))

fig, loss_ax = plt.subplots()
acc_ax = loss_ax.twinx()

loss_ax.plot(hist.history['loss'], 'y', label='train loss')
loss_ax.plot(hist.history['val_loss'], 'r', label='val loss')

acc_ax.plot(hist.history['accuracy'], 'b', label='train acc')
acc_ax.plot(hist.history['val_accuracy'], 'g', label='val acc')

loss_ax.set_xlabel('epoch')
loss_ax.set_ylabel('loss')
acc_ax.set_ylabel('accuracy')

loss_ax.legend(loc='upper left')
acc_ax.legend(loc='lower left')

plt.show()

일부러 신경망을 512, 256, 128, 64, 32, 10으로 적층 시켜 테스트를 해보면 다음과 같은 결과를 얻게 됩니다.

GPU 사용:  0:01:36.024432
CPU 사용:  0:01:29.706344

이전에는 3배나 빨랐던 CPU 학습이 이젠 GPU와 비교해 차이가 많이 줄었습니다. 이런 점을 고려해봤을 때, 학습시 epochs 옵션을 1로 놓고 CPU와 GPU의 속도를 테스트한 다음 진행하는 것도 좋을 것입니다.




자신의 PC에 설치된 NVidia CUDA Toolokt 버전이 예전 것이고, 그 버전을 고수해야 한다면 tensorflow의 버전을 낮춰서 설치해야 합니다. 이에 대해서는 다음의 글을 참고하세요.

tensorflow 에러 해결: Could not load 'cudart64_110.dll'; dlerror:
; https://deep-deep-deep.tistory.com/71

Tensorflow 에러 해결: Could not load dynamic library
; https://deep-deep-deep.tistory.com/83

또한, 웹에 검색해 보면 tensorflow-gpu를 설치하라는 글이 나오는데,

pip install tensorflow-gpu

"https://www.tensorflow.org/install/gpu" 링크를 보면, 그건 지난 1.15 이하 버전의 tensorflow인 경우를 대상으로 합니다.




GPU 사용 관련한 공식 문서는 아래에 있습니다.

Use a GPU
; https://www.tensorflow.org/guide/gpu

GPU가 1개 이상이라면 본문의 예제를 다음과 같이 변경해 수행해 볼 수 있을 텐데요,

# [TF 2.x] TensorFlow 2.0에서 multi GPU 사용하기 - 텐서플로우 문제 해결
# ; https://lv99.tistory.com/12
mirrored_strategy = tf.distribute.MirroredStrategy()

with mirrored_strategy.scope():
    model = Sequential()
    model.add(Dense(20, input_dim=2, activation='relu'))
    model.add(Dense(10, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))

    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

제가 NVidia GPU가 하나밖에 없어서 테스트를 할 수 없었지만, 어쨌든 1개인 상태에서 저렇게 코드를 바꿔도 동작은 합니다. 단지, 뭔가 쓸데없는 코드가 수행돼서 그런지 다음과 같이 오히려 1회 학습 시간이 배나 걸리는 것을 확인할 수 있습니다.

...[생략]...
20/20 [==============================] - 0s 12ms/step - loss: 0.1951 - accuracy: 0.9250 - val_loss: 0.2019 - val_accuracy: 0.9050
Epoch 197/200
20/20 [==============================] - 0s 11ms/step - loss: 0.1870 - accuracy: 0.9350 - val_loss: 0.1855 - val_accuracy: 0.9300
Epoch 198/200

elapsed:  0:00:52.010992  // i5-4670 CPU인 경우




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 8/31/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2021-08-31 10시50분
[승준] CUDA 사용량 보시려면 작업관리자에서 video encoder를 마우스로 선택하여 cuda로 바꾸시면
됩니다. 사용량은 제대로 나오더군요.
그보다도 저놈의 텐서플로우 문제점은 버전별로 호환성이 바닥이라는거죠.
rtx 3000대 그래픽 카드로는 텐서 1.x대 만들어진 소스는 테스트 조차도 불가능 합니다.
[guest]
2021-08-31 06시43분
@승준 감사합니다. ^^ 너무 좋은 팁이라 저처럼 모르는 분들을 위해 간단하게 다음의 글로 정리했습니다. ^^

윈도우 - 작업 관리자에서 (tensorflow 등으로 인한) GPU 연산 부하 보는 방법
; https://www.sysnet.pe.kr/2/0/12818

지금까지 단 한 번도, 보이는 패널의 내용을 바꾸기 위한 버튼을 눌러볼 생각을 못했군요. ^^
정성태

1  2  3  4  5  6  7  8  9  10  11  12  [13]  14  15  ...
NoWriterDateCnt.TitleFile(s)
13294정성태3/22/20234122.NET Framework: 2105. LargeAddressAware 옵션이 적용된 닷넷 32비트 프로세스의 가용 메모리 - 두 번째
13293정성태3/22/20234191오류 유형: 853. dumpbin - warning LNK4048: Invalid format file; ignored
13292정성태3/21/20234305Windows: 232. C/C++ - 일반 창에도 사용 가능한 IsDialogMessage파일 다운로드1
13291정성태3/20/20234712.NET Framework: 2104. C# Windows Forms - WndProc 재정의와 IMessageFilter 사용 시의 차이점
13290정성태3/19/20234219.NET Framework: 2103. C# - 윈도우에서 기본 제공하는 FindText 대화창 사용법파일 다운로드1
13289정성태3/18/20233416Windows: 231. Win32 - 대화창 템플릿의 2진 리소스를 읽어들여 자식 윈도우를 생성하는 방법파일 다운로드1
13288정성태3/17/20233515Windows: 230. Win32 - 대화창의 DLU 단위를 pixel로 변경하는 방법파일 다운로드1
13287정성태3/16/20233683Windows: 229. Win32 - 대화창 템플릿의 2진 리소스를 읽어들여 윈도우를 직접 띄우는 방법파일 다운로드1
13286정성태3/15/20234146Windows: 228. Win32 - 리소스에 포함된 대화창 Template의 2진 코드 해석 방법
13285정성태3/14/20233737Windows: 227. Win32 C/C++ - Dialog Procedure를 재정의하는 방법파일 다운로드1
13284정성태3/13/20233937Windows: 226. Win32 C/C++ - Dialog에서 값을 반환하는 방법파일 다운로드1
13283정성태3/12/20233478오류 유형: 852. 파이썬 - TypeError: coercing to Unicode: need string or buffer, NoneType found
13282정성태3/12/20233807Linux: 58. WSL - nohup 옵션이 필요한 경우
13281정성태3/12/20233716Windows: 225. 윈도우 바탕화면의 아이콘들이 넓게 퍼지는 경우 [2]
13280정성태3/9/20234453개발 환경 구성: 670. WSL 2에서 호스팅 중인 TCP 서버를 외부에서 접근하는 방법
13279정성태3/9/20233997오류 유형: 851. 파이썬 ModuleNotFoundError: No module named '_cffi_backend'
13278정성태3/8/20233945개발 환경 구성: 669. WSL 2의 (init이 아닌) systemd 지원 [1]
13277정성태3/6/20234576개발 환경 구성: 668. 코드 사인용 인증서 신청 및 적용 방법(예: Digicert)
13276정성태3/5/20234306.NET Framework: 2102. C# 11 - ref struct/ref field를 위해 새롭게 도입된 scoped 예약어
13275정성태3/3/20234660.NET Framework: 2101. C# 11의 ref 필드 설명
13274정성태3/2/20234252.NET Framework: 2100. C# - ref 필드로 ref struct 타입을 허용하지 않는 이유
13273정성태2/28/20233953.NET Framework: 2099. C# - 관리 포인터로서의 ref 예약어 의미
13272정성태2/27/20234202오류 유형: 850. SSMS - mdf 파일을 Attach 시킬 때 Operating system error 5: "5(Access is denied.)" 에러
13271정성태2/25/20234142오류 유형: 849. Sql Server Configuration Manager가 시작 메뉴에 없는 경우
13270정성태2/24/20233754.NET Framework: 2098. dotnet build에 /p 옵션을 적용 시 유의점
13269정성태2/23/20234290스크립트: 46. 파이썬 - uvicorn의 콘솔 출력을 UDP로 전송
1  2  3  4  5  6  7  8  9  10  11  12  [13]  14  15  ...