이번 강의에서는 deep learning을 위한 소프트웨어들을 배울 것이다.
가장 먼저 cpu와 gpu에 대한 비교부터 시작된다.


CPU는 이렇게 조그맣게 생겼고 쿨러가 별도로 있다.

GPU는 비교적 크고, 쿨러도 내장으로 달려있다. GPU회사에는 크게 두군데가 나눠먹고 있는데 NVIDIA와 AMD다. 그런데 딥러닝에서는 대부분 NVIDIA가 지배적이다.
위에서 예시를 들었던 행렬곱에 대해서 얘기해 보자면

행렬곱 연산자 앞쪽 행렬의 행백터와 뒤쪽 행렬의 열벡터를 내적하는 것과 같다. 각 벡터들에 대한 내적연산은 모두 독립적으로 수행(내적연산간에 값을 주고받는게 없다)되기 때문에 병렬연산이 가능하고, 각 연산을 코어들에 분산시켜서 매우 빠르게 연산할 수 있다.

gpu로 프로그래밍을 할 때는 몇 가지 소프트웨어가 필요하다. 대표적으로 CUDA가 있다. CUDA는 NVIDIA에서 사용하는 소프트웨어인데 c비슷한 코드로 짜서 gpu에서 바로 작동하는 소프트웨어다.high level API를 제공한다. cuBLAS는 행렬곱을 비록한 행렬연산을 제공하는데 이론적으로 하드웨어의 사용가능한 최대치까지 활용한다. 그리고 cuDNN은 특히 중요한데 convolution layer, forward pass, backward pass, batch normalization, RNN등 딥러닝에 피요한 기초적인 연산을 전부 제공하는 API다. OpenCL은 CUDA와 비슷한데 NVIDIA 뿐만 아니라 AMD gpu나 cpu에서도 동작한다. 그런데 CUDA보다는 성능이 떨어진다는 단점이 있다.
성능을 비교해보면 다음과 같다.

위의 비교에서는 각 모델에 대해서 얼마나 시간이 걸렸는지를 비교한 것이다. 파란색 그래프는 cpu를 사용한 경우고, 노란색은 cuDNN을 사용한 gpu에서의 시간이다. 위에서 보면 ResNet-200돌렸을 때는 둘 사이의 차이가 76배나 난다. 그런데 이건 사실 cpu는 이 task에 대해 최적화가 잘 되어 있지 않기 때문에 약간 불공평하다고 할 수 있다.

그래서 gpu간에 비교를 해보면 빨간색은 cuDNN을 사용하지 않은 최적화 되지 않은 CUDA인데 ResNet-200에서 보면 노란색과 거의 3배가량 차이가 난다.

그런데 이렇게 뛰어난 것 같은 gpu에도 몇가지 문제사항이 있다. 모델은 gpu에서 학습되지만 데이터는 RAM을 통해서 읽어진다는 점이다. 디스크에서 데이터를 읽어 RAM으로 가져와서 그 데이터를 GPU로 보내는 건데 이 작업에 신경쓰지 않으면 병목현상이 발생한다. 그래서 나온 해결책은 데이터셋이 작은 경우나 서버의 RAM용량이 크다면 모든 데이터를 RAM에 읽어놔 버리는 방법이 있고, HDD대신에 SDD를 사용해서 처리 속도를 높이는 방법이 있다. 이 방법들은 하드웨어적인 것이고, 소프트웨어적으로는 CPU에서 멀티쓰레딩을 해서 데이터를 미리미리 가져오는 것이다. 그리고 나서 buffer에서 gpu로 데이터를 바로바로 전송시키면 성능의 향상이 가능하다.
구체적인 예시로 설명하자면 순차적인 방법: 디스크에서 데이터를 읽는다→미니배치의 데이터가 다 읽힐 때까지 기다린다→미니배치를 gpu에 전송한다→gpu에서 forward/backward pass를 수행한다→또 다른 미니배치를 읽는다. 멀티쓰레딩: cpu에서 멀티쓰레딩을 통해 디스크에서 데이터를 불러오는 백그라운드 작업을 하고 있다면 gpu가 계산하는 동안 cpu의 백그라운드 쓰레드는 디스크에서 데이터를 불러온다. 이때 cpu의 메인쓰레드 에서는 synchronization만 관리하면 모든 작업이 병렬로 수행 가능하다. 그리고 이러한 작업관리는 cuDNN같은 딥러닝 프레임워크에 이미 다 구현이 되어 있어서 그냥 쓰기만 하면 된다.