딥러닝에서 CPU와 GPU 성능 비교
1. DNN (Dense) 모델 학습측정
딥러닝 모델을 만들 때 꼭 GPU가 필요할까?라는 의문을 가진 적이 있을 것이다. LLM이나 해상도 높은 동영상에서 정밀하게 측정할 부분이 있다면 당연히 필요하겠지만, 101 과정에서 연습을 한다면 GPU가 꼭 필요할까? 어느 정도 특성을 가진 데이터를, 어느 정도의 정확도를 가지도록 만드는데 어느 정도의 성능이 필요할까? 어떤 모델에는 꼭 필요하고 어떤 모델에는 CPU도 가능할까? 에 대한 의문을 테스트하기 위해 내가 가지고 있는 노트북을 기준으로 한번 실험해 보았다.
1. MNIST + Dense Sequential 모델에서 CPU와 GPU학습 비교
첫 번째 테스트할 데이터는 MNIST이고, Dense (완전 연결 층) 3개를 가지고 있는 Sequential모델로 Hands-On Machine Learning의 CNN에 나오는 모델로 이미지를 처리하는 모델 중에 가장 간단한 분류(Classification)를 위한 모델이다. MNIST는 숫자 쓴 글자에 대한 이미지를 깨끗하게 전처리 한 후 28 * 28 크기로 정리해 놓은 60000개의 학습용 데이터와 10000개의 이미지 데이터이기 때문에, 모델을 만들면 이미지에서 숫자를 인식하게 된다는 것을 의미한다.
학습에 사용할 모델은 아래와 같이 Dense (Fully connected) 층만을 사용하는 모델로 266,610개의 파라미터를 학습시켜야 한다는 것을 의미한다.
앞에서 설치한 PyTorch기반의 Keras에서 테스트했으며, 한 번은 GPU로 한 번은 CPU로 학습을 시켰다.
하드웨어 환경 |
|
CPU | Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz 2.30 GHz |
RAM | 16.0 GB (15.8 GB usable) |
GPU | NVIDIA GeForce RTX 3060 |
VRAM | 6144 GB |
소프트웨어 환경 | |
Python | 3.10.11 |
PyTorch | 2.4.1 + cu118 |
Keras | 3.6.0 (PyTorch Backend) |
Jupyterlab | 4.2.5 |
MNIST는 28 x 28의 낮은 해상도와 하나의 채널만 있는 간단한 이미지로, 쉽게 어떤 물건인지 알 수 있을 정도로 특성이 뚜렷하게 전처리 하였고 분류 종류도 10가지로 제한된 실험 데이터이어서 CNN을 사용하지 않아도 쉽게 분류가 된다.
파이썬 프로그램은 지난번에 노트북 설치를 테스트할 때 사용했던 아래 코드를 사용했다.
import os
os.environ["KERAS_BACKEND"] = "torch"
from keras import datasets, Input
from keras.models import Sequential
from keras.layers import Dense, Flatten
(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()
x_train = x_train / 255.0
x_test = x_test / 255.0
model = Sequential([
Input(shape=(28, 28, )),
Flatten(),
Dense(300, activation="relu"),
Dense(100, activation="relu"),
Dense(10, activation="softmax")
])
model.compile(loss="sparse_categorical_crossentropy", optimizer="sgd", metrics=["accuracy"])
%%timeit -n1 -r1
history = model.fit(x_train, y_train, epochs=20, validation_split=0.15,)
a. GPU로 모델 학습한 결과
전체 20 Epoch를 도는 동안 아래와 같이 4분 16초가 걸렸고 각 Epoch를 처리할 때마다 13초 정도가 걸렸다.
Epoch 1/20
1594/1594 ━━━━━━━━━━━━━━━━━━━━ 13s 8ms/step - accuracy: 0.7163 - loss: 1.0640 - val_accuracy: 0.9169 - val_loss: 0.2983
Epoch 2/20
1594/1594 ━━━━━━━━━━━━━━━━━━━━ 13s 8ms/step - accuracy: 0.9099 - loss: 0.3150 - val_accuracy: 0.9334 - val_loss: 0.2358
...
Epoch 19/20
1594/1594 ━━━━━━━━━━━━━━━━━━━━ 13s 8ms/step - accuracy: 0.9847 - loss: 0.0575 - val_accuracy: 0.9766 - val_loss: 0.0852
Epoch 20/20
1594/1594 ━━━━━━━━━━━━━━━━━━━━ 13s 8ms/step - accuracy: 0.9864 - loss: 0.0522 - val_accuracy: 0.9759 - val_loss: 0.0827
4min 16s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
b. CPU로 모델 학습한 결과
CPU로 학습하기 위해 아래 Jupyter Kernel을 다시 시작하고 아래를 실행해서 PyTorch가 CPU를 사용하도록 설정한다.
import torch
torch.cuda.is_available = lambda: False
20 Epoch를 도는 동안 아래와 같이 3분 14초가 걸렸고 각 Epoch를 처리할 때마다 약 9초 정도가 걸렸다.
Epoch 1/20
1594/1594 ━━━━━━━━━━━━━━━━━━━━ 9s 6ms/step - accuracy: 0.7026 - loss: 1.0917 - val_accuracy: 0.9168 - val_loss: 0.2980
Epoch 2/20
1594/1594 ━━━━━━━━━━━━━━━━━━━━ 11s 7ms/step - accuracy: 0.9118 - loss: 0.3101 - val_accuracy: 0.9320 - val_loss: 0.2369
...
Epoch 19/20
1594/1594 ━━━━━━━━━━━━━━━━━━━━ 10s 6ms/step - accuracy: 0.9850 - loss: 0.0565 - val_accuracy: 0.9743 - val_loss: 0.0869
Epoch 20/20
1594/1594 ━━━━━━━━━━━━━━━━━━━━ 9s 6ms/step - accuracy: 0.9862 - loss: 0.0524 - val_accuracy: 0.9747 - val_loss: 0.0856
3min 14s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
학습할 퍼셉트론 수가 많지 않은 경우 하나의 core 성능이 더 많은 영향을 미쳐 CPU가 더 빠른 것을 알 수 있다.
2. CIFA-100 + Dense Sequential 모델에서 CPU와 GPU학습 비교
이번에는 CIFA-100 데이터를 MNIST와 같은 Dense Layer로 학습시켜 보기로 했다. 구분해야 할 이미지의 종류(Category)가 100개 이기 때문에 연결층의 개수를 더 늘리고 학습을 시켜 보기로 했다.
수정한 모델은 아래와 같이 연결층을 많이 늘렸기 때문에 앞의 모델보다 13배 정도 더 많은 파라미터를 학습시켜야 한다.
모델을 바꾸고 CIFA-100으로 데이터를 바꾼 파이썬 프로그램은 아래와 같다.
import os
os.environ["KERAS_BACKEND"] = "torch"
from keras import datasets, Input
from keras.models import Sequential
from keras.layers import Dense, Flatten
from keras.utils import to_categorical
(x_train, y_train), (x_test, y_test) = datasets.cifar100.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
y_train = to_categorical(y_train, 100)
y_test = to_categorical(y_test, 100)
model = Sequential([
Input(shape=(32, 32, 3)),
Flatten(),
Dense(1000, activation="relu"),
Dense(500, activation="relu"),
Dense(100, activation="softmax")
])
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])
%%timeit -n1 -r1
history = model.fit(x_train, y_train, epochs=100, validation_split=0.15,)
a. GPU로 모델 학습한 결과
20 Epoch를 도는 동안 아래와 같이 3분 47초가 걸렸고 각 Epoch를 처리할 때마다 약 11초 정도가 걸렸다.
Epoch 1/20
1329/1329 ━━━━━━━━━━━━━━━━━━━━ 11s 8ms/step - accuracy: 0.0520 - loss: 4.3354 - val_accuracy: 0.1085 - val_loss: 3.8779
Epoch 2/20
1329/1329 ━━━━━━━━━━━━━━━━━━━━ 11s 9ms/step - accuracy: 0.1340 - loss: 3.7058 - val_accuracy: 0.1540 - val_loss: 3.5973
...
Epoch 19/20
1329/1329 ━━━━━━━━━━━━━━━━━━━━ 11s 9ms/step - accuracy: 0.3109 - loss: 2.6925 - val_accuracy: 0.2001 - val_loss: 3.6410
Epoch 20/20
1329/1329 ━━━━━━━━━━━━━━━━━━━━ 11s 9ms/step - accuracy: 0.3094 - loss: 2.6969 - val_accuracy: 0.2105 - val_loss: 3.6128
3min 47s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
20 Epoch를 돌아도 정확도가 30% 정도로 매우 낮을 것을 알 수 있다. 그래서 100 Epoch를 돌려 봤지만 결과는 여전히 50% 미만으로 나왔다.
...
Epoch 99/100
1329/1329 ━━━━━━━━━━━━━━━━━━━━ 11s 9ms/step - accuracy: 0.4763 - loss: 1.9644 - val_accuracy: 0.1844 - val_loss: 5.5001
Epoch 100/100
1329/1329 ━━━━━━━━━━━━━━━━━━━━ 11s 8ms/step - accuracy: 0.4762 - loss: 1.9640 - val_accuracy: 0.1891 - val_loss: 5.4909
18min 46s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
b. CPU로 모델 학습한 결과
20 Epoch를 도는 동안 아래와 같이 12분 9초가 걸렸고 각 Epoch를 처리할 때마다 약 35초 이상이 걸렸다.
Epoch 1/20
1329/1329 ━━━━━━━━━━━━━━━━━━━━ 34s 26ms/step - accuracy: 0.0520 - loss: 4.3273 - val_accuracy: 0.1159 - val_loss: 3.8247
Epoch 2/20
1329/1329 ━━━━━━━━━━━━━━━━━━━━ 36s 27ms/step - accuracy: 0.1364 - loss: 3.7087 - val_accuracy: 0.1653 - val_loss: 3.5844
...
Epoch 19/20
1329/1329 ━━━━━━━━━━━━━━━━━━━━ 37s 28ms/step - accuracy: 0.3078 - loss: 2.7025 - val_accuracy: 0.2145 - val_loss: 3.5165
Epoch 20/20
1329/1329 ━━━━━━━━━━━━━━━━━━━━ 40s 30ms/step - accuracy: 0.3123 - loss: 2.6656 - val_accuracy: 0.2052 - val_loss: 3.6055
12min 9s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
CPU로 모델을 학습시켰을 때에는 계산양이 늘어나면서 그에 비례해서 학습시간이 늘어나는 것을 볼 수 있었지만, 계산할 수 있는 CPU에 비해 core수가 훨씬 많은 GPU를 사용하면 계산할 양이 늘어났음에도 학습시간이 비례해서 길어지지 않는 것을 확인할 수 있었다. 따라서, 학습해야할 파라미터가 늘어나면 각 core의 성능보다 core의 수가 영향을 더 많이 미치는 것을 확인할 수 있다.
'프로그램 개발' 카테고리의 다른 글
React Native로 PDF Viewer 앱 만들기; 2. react-native-pdf 테스트 (0) | 2024.11.12 |
---|---|
딥러닝에서 CPU와 GPU 성능 비교; 2. CNN (Conv2D) 모델 학습 측정 (0) | 2024.10.31 |
엔비디아 Jetson Xavier; 4. PyTorch 설치 후 MNIST 학습 테스트 (1) | 2024.10.28 |
엔비디아 Jetson Xavier; 3. Tensorflow (+ Keras) 설치 (7) | 2024.10.27 |
NestJS 개발 시작하기(로그인 인증 개발); 7. 암호화와 해쉬 함수 (3) | 2024.10.17 |