1. 고정 기능에서 쉐이더로

 

최근 GPU의 아키텍처 업데이트가 점점 빨라지고 있습니다. 특히 GPGPU 세대가 되면서 그 진화 속도는 급격히 빨라졌으며, 그 결과 이전의 GPU와는 다른 형태인 연산 장치(Computation Unit)로 진화했습니다. 그래서 기본으로 되돌아가 GPU에 대해 설명하고자 합니다.

 

GPU라는 이름이 나오기 이전인 그래픽 컨트롤러 수준까지 거슬러 올라가면, 그래픽 컨트롤러는 메모리를 데이터로 채우는 것이 주요 기능입니다. 그런 의미에서는 연산기보다는 메모리 컨트롤러에 필요한 기능을 추가했다고 보는 쪽에 더 가깝겠습니다.

 

그러나 기능이 늘어나면서 연산을 담당하는 기능도 늘어나게 됐습니다. 예를 들어 화면 전체의 색조를 조금 바꾸는 렌더링 작업을 하고 싶다고 가정해 봅시다. 화면이 1개의 점으로 구성되어 있다면 이건 매우 간단하게 처리할 수 있습니다. (R, G, B)=(00,00, FF)에서 (R, G, B)=(00, C8, C8)으로 바꾸려면 프레임 버퍼에 (R, G, B)=(00, C8, C8)라는 데이터를 덮어 씌우면 되니까요. 이 경우 따로 연산 기능이 들어갈 필요는 없습니다.

 

1.jpg

 

같은 화면을 새로 고침

 

2.jpg

 

다른 내용의 화면을 표시하기

 

문제는 그런 경우가 별로 없다는 겁니다. 아래 예시처럼 A, B, C의 3개 점으로 이루어졌을 경우엔

 

A:(R,G,B)=(00,00,FF)
B:(R,G,B)=(BA,BA,FF)
C:(R,G,B)=(FF,FF,FF)

 

이 되니까 색조를 바꾼 A'~C'의 픽셀 값은

 

A':(R,G,B)=(00,C8,C8)
B':(R,G,B)=(BA,E5,E5)
C':(R,G,B)=(FF,FF,FF)

 

으로 변환하는 작업이 있어야 합니다. 이 경우 첫번째 예처럼 무턱대고 색을 바꾸는 건 불가능하고, 프레임 버퍼에서 픽셀 데이터를 읽어 내고, 그 값에 따라 변경 후의 값을 계산하고, 그것을 프레임 버퍼에 다시 기록하는 작업이 필요하게 됩니다. 초기의 PC에서는 이러한 계산을 모두 CPU에서 수행했으며, 새로 그려낼 값을 하나씩 계산해 비디오 카드의 프레임 버퍼에 올렸습니다. 당연히 화면을 새로 그리는 데 시간이 오래 걸리게 되지요. 그래서 그래픽 컨트롤러에도 간단한 연산기를 탑재해 이러한 픽셀 값 변경을 고속으로 처리하는 것, 이것이 GPU가 생긴 원래 목적입니다.

 

다만 GPU의 초창기에는 연산 유닛 자체는 갖고 있었지만 프로세서라고는 부르기 힘들었습니다. 그 이유는-

 

연산 처리 자체는 하지만 프로그램을 동적으로 해석하는 기능은 없거나 가지고 있어도 한정적임

실행 제어 기능은 거의 없음

특수한 함수 등도 거의 없음

 

같은 구성이기 때문입니다. 더 정확히 말하면 연산이 사실상 Y=A×X+B처럼 단일 곱셈-덧셈에 한정되어 있었습니다. A와 B는 외부(CPU측)에서 설정하는 형태입니다. 그런 의미에서는 초창기 그래픽 칩 내부의 연산기는 DSP(Digital Signal Processor)에 가깝다고 할 수 있겠습니다. 

 

참고로 이 당시, 대충 다이렉트 X 6 세대까지는 대부분이 SISD(Single Instruction, Single Data) 구성의 연산기를 사용했습니다.

 

예를 들어 NVIDIA의 리바 128 같은 경우 코어와 메모리의 클럭은 모두 100MHz, 버스 폭은 128비트입니다. 이 버스 폭을 최대한 살리려면 당시에는 16bpp(bit per pixel)의 하이 컬러 구성이라 1사이클 당 128÷16=8픽셀의 렌더링이 필요하게 됩니다. 실제론 메모리에 읽기/쓰기가 모두 필요하니 대역폭을 대충 절반으로 잡아도 1사이클 당 4픽셀의 렌더링 출력이 가능하지만, 실제 리바 128의 픽셀 필레이트(프레임 버퍼에 픽셀을 채워넣는 속도)는 최대 100MPixel/sec에 불과합니다. 즉 1사이클당 1픽셀이니 16비트의 단일 곱셈-덧셈 연산기가 1개만 들어 있는 구조입니다.

 

이것이 다이렉트 X 7 세대가 되면서 여러가지 변화가 생겨나게 됩니다. 우선 하나는 하드웨어 T&L의 지원입니다. T&L은 Transformation&Lighting의 줄임말로 모델의 이동과 회전(변형)의 계산과 조명 효과 계산을 수행하는 것입니다. 다이렉트 X 6까지는 극단적으로 말해서 2D 그래픽의 연장선상에 있었습니다. 원래 3D 게임은 우선 가상 3D공간 안에 그리고 싶은 오브젝트(물체)를 배치하고 그 물체를 어디서 어떻게 보는지에 해당하는 뷰포트를 배치한 후, 마지막으로 해당 물체에 어떻게 조명이 들어가는지를 설정합니다. 이것은 다이렉트 3D 뿐만 아니라 CG에서도 3차원 모델링을 할 때 일반적인 절차이며, 다이렉트 X 6까지 이 작업은 모두 CPU(소프트웨어)에서 수행했습니다. 다이렉트 X 7이 되면서 이를 하드웨어 쪽에서 처리하도록 바뀐 것입니다. 

 

이를 지원하기 위해서 무엇이 필요할까요? 우선 물체의 회전과 이동의 계산을 하기 위한 3차원 벡터 연산을 실시할 필요가 있습니다. 이 때엔 적어도 부동 소수점 곱셈과 덧셈이 필요합니다. 또 수평 이동 뿐만 아니라 회전까지 커버하기 위해서는 간단한 삼각 함수(사인과 코사인이면 됨)가 없으면 불편합니다. 일반적으로 3차원 벡터를 취급하는 경우엔 3차 행렬로 다루는 것이니, 간단히 말해서 하드웨어 T&L은 행렬 전용 연산기가 추가됐다고 할 수 있습니다.

 

이것은 버텍스 연산이라 부르기도 합니다. 다수의 삼각형(폴리곤)을 조합해 3차원 물체를 만든 다음, 각각 삼각형의 위치를 변화시켜 이동이나 회전 변형을 표현하기 때문입니다. 삼각형의 위치를 계산하려면 삼각형에 존재하는 3개 버텍스의 좌표를 변화시켜야 하니까요. 이 처리를 수행하기 위한 기능이 기존의 연산기와 별도로 들어간 것입니다.

 

또 다른 하나는 이러한 그러한 연산기의 병렬화입니다. 예를 들어 다이렉트 X 7을 처음으로 대응한 제품 중 하나인 지포스 256의 경우 120MHz로 동작하며 픽셀 레이트는 480MPixel/sec이고 1사이클당 4픽셀의 처리가 가능합니다. 이를 실현하기 위해 연산기는 16비트 폭이 4개씩 나란히 SIMD 형태로 확장되어 있습니다. 다만 어디까지나 SIMD와 비슷한 형태라 자유롭게 프로그래밍을 실행할 순 없습니다. 

 

 

GPU에 변혁을 가져온 프로그래머블 쉐이더의 등장

 

여기까지는 과거의 연장이라는 형태로 성능을 높여 왔지만, 다이렉트 X 8에서 프로그래머블 쉐이더라는 개념이 나오면서 내부 구성이 크게 달라지게 됐습니다.

 

아래 그림은 다이렉트 X 7까지 내부 렌더링의 흐름(그래픽 파이프라인이라 부릅니다)을 간단히 줄여서 그린 것입니다. 우선 버텍스를 계산하고 카메라(시점)에서 보이지 않는 곳의 데이터를 잘라내는 처리(그림자 처리도 여기에 포함)는 하드웨어 T&L에서 이루어집니다. 이후 이를 2차원 데이터로 바꾸는 라스터라이즈를 거치고 무늬와 외모에 해당하는 텍스처를 붙이는데, 미리 텍스처를 불러와 실제 형태에 맞춰 변형한 후 맞춰 붙이게 됩니다. 마지막으로 이를 프레임 버퍼에 출력하면 끝나게 되며 이 중 ALU에 해당하는 범용 연산기를 사용하는 건 마지막 부분이고, 나머지는 하드웨어 T&L과 전용 회로로 구성되어 있었습니다.

 

3.jpg

 

그래픽 파이프라인의 그래픽 처리 흐름

 

그런데 다이렉트 X 8 이후엔 그런 고정 처리를 없애고 프로그램에서 자유롭게 설정을 바꿀 수 있게 됩니다. 그 결과 64비트 폭의 SIMD가 1개만 있던 것에서 벗어나 다수의 SIMD 연산기를 적절히 조합해 쓸 수 있게 됩니다.

 

4.jpg

 

쉐이더가 등장한 후의 그래픽 처리 과정

 

5.jpg

 

프로그래머블 쉐이더의 등장으로 SIMD 연산기를 조합해서 처리

 

또 다른 차이는 지금까지 단순한 연산기만 있던 것에서 벗어나 쉐이더가 되면서, 자유롭게 프로그램을 해석/실행할 수 있데 됐다는 것입니다. 쉐이더는 이후 다이렉트 X10의 통합 쉐이더로 발전하게 됩니다. 전에는 버텍스와 픽셀 쉐이더가 완전히 분리되어 있었지만 그 구별이 사라진 것입니다. 버텍스 쉐이더는 하드웨어 T&L의 부동 소수점 연산이 가능했지만 픽셀 쉐이더는 정수 연산만 할 수 있었는데, 통합 쉐이더가 되면서 모든 쉐이더가 정수와 부동소수점 연산이 가능하게 됐습니다.

 

이런 쉐이더의 진화와 제조 공정의 미세화가 진행되면서 성능을 높이기 위해 쉐이더의 수를 늘리는 식으로 GPU가 발전하게 됩니다. 다이렉트 X 8 이후의 NVIDIA의 주요 제품 쉐이더 수를 보면-

 

지포스 3 Ti: 버텍스 x1, 픽셀 x4

지포스 4 Ti: 버텍스 x2, 픽셀 x4
지포스 FX: 버텍스 x3, 픽셀 x4
지포스 6000: 정상×6, 픽셀 x16
지포스 7000: 정상×8, 픽셀 x24
지포스 8000: 통합×128
지포스 9000: 통합×128
지포스 100: 통합×128
지포스 200: 통합×240
지포스 300: 통합×112
지포스 400: 통합×480
지포스 500: 통합×512
지포스 600: 통합×1,536
지포스 700: 통합×2,880


가 됩니다(위 모델들은 모두 각 세대 하이엔드 제품의 스펙). 제품마다 리네이밍 이루어지거나 지포스 300 시리즈처럼 저가형으로만 나온 경우도 있어, 스펙이 변하지 않거나 스펙이 떨어진 경우도 있긴 하지만, 크게 보면 쉐이더의 수를 늘려 성능을 강화했음을 알 수 있습니다.

 

다만 이 경우 원래 쉐이더를 단순한 SIMD로 대체해도 되는지, 쉐이더 사이의 연계를 어떻게 할 것인지, 전체 관리를 어떻게 할 것인지 등의 문제가 발생합니다. 또 이렇게 많은 연산 유닛을 다른 용도로 쓰는 것도 연구하게 되지요.

 

그러나 이런 용도에 쓰려면 대량의 쉐이더를 효율적으로 작동시킬 필요가 있습니다. 그리고 이 '효율적인 작동'을 실현하는 방법은 AMD(ATI)와 NVIDIA가 크게 달랐습니다. 나중에는 비슷해졌지만. 어쨌건 그 차이가 GPU의 구조를 알기 어렵게 한 요소라 생각됩니다.

 

 

2. NVIDIA 아키텍처의 변화

 

GPU에 본격적인 쉐이더가 처음으로 구현된 건 다이렉트 X 8 세대에 있었던 일입니다. 엄밀히 말하면 다이렉트 X 7인 NV20이 쉐이더 모델 1.0을 지원하긴 했지만. 이를 처음으로 지원한 건 NVIDIA의 경우 NV25, 지포스 4 시리즈였습니다. 이 때엔 쉐이더 프로그램의 수준은 그리 높지 않았고 다이렉트 X 7 세대와 구조도 별로 변하지 않았습니다.

 

NV25는 NV20(지포스 3)의 발전형으로 주로 픽셀 쉐이더를 강화했습니다. 다이 크기의 한계로 픽셀 파이프라인 그 자체는 4개를 유지하며 출력 량을 높여 렌더링 성능을 높였습니다.

 

6.jpg

 

이 세대의 쉐이더는 어떤 구조였을까요? 직접적인 답은 아니지만 간접적인 답은 있습니다. 이 사진은 마이크로스프트가 멜트다운 2001에서 쉐이더 1.x 세대의 레퍼런스 구성을 설명한 것입니다. 하드웨어의 물리적인 구현은 일단 접어두고 애플리케이션(쉐이더 프로그램)에서 하드웨어가 어떻게 드러나는지를 정리한 것입니다. 우선 버텍스 쉐이더 벡터 데이터를 바탕으로 어느 픽셀은 어떤 식으로 어떤 조직을 표시해야 하는가라는 버텍스 기능을 산출해 닙니다. 이어서 픽셀 쉐이더가 이를 바탕으로 텍스처를 그려 픽셀 데이터를 만들어 출력하는 흐름이 됩니다.

 

7.jpg

 

이 쉐이더 1.x 세대는 몇가지 버전이 있으며 다이렉트 X 8.1에선 픽셀 쉐이더 1.2/1.3/1.4가 있지만 큰 차이는 없습니다.

 

8.jpg

 

참고로 NVIDIA는 지포스 4에서 PS 1.2/1.3을 지원하며, PS 1.4는 ATI(지금은 AMD)의 라데온 9000 시리즈에서만 구현된 기능입니다. 그리고 이 픽셀 쉐이더의 내용이 소프트웨어에서 어떻게 보이는지를 설명한 것이 이 사진으로, 2개의 입력을 컬러와 알파 채널로 나누고 계산을 해서 출력하는 형태로 구성됩니다. 물론 실제 하드웨어가 딱 저렇다는 게 아니라 소프트웨어에선 저렇게 받아들인다는 이야기입니다.

 

 

극적인 변화가 이룬 실패작, 지포스 FX

 

9.jpg

 

그런데 NVIDIA는 다이렉트 X 9 세대에서 내부 구조를 대거 바꾸게 되는데 그것이 바로 NV30인 지포스 FX입니다. 이 때 NVIDIA는 CineFX라 불리는 큰 폭의 내부 확장을 실장했으며 내부 구성을 극적으로 바꿨습니다.

 

10.jpg

 

기존 GPU와의 차이를 간단하게 말하면, 지금까진 이 그림의 왼쪽처럼 명령 발행에서 다수의 픽셀 파이프라인을 대상으로 명령을 내렸지만, NV30에선 픽셀 파이프라인은 1개고 여기에 다수의 쉐이더가 연결되는 방식이 됩니다. 이걸 CPU로 비유하면 기존의 GPU가 멀티코어 아톰 프로세서로 코어 1개(쉐이더)의 성능은 그리 높지 않지만 코어 수를 늘려 전체 성능을 높인 반면, NV30은 하스웰이나 아이테니엄처럼 오직 IPC를 늘리는 방향으로 나간 것입니다. 이 경우 쉐이더는 CPU 코어라기보다는 코어 내부의 실행 유닛에 해당됩니다.

 

이렇게 복잡한 구성을 쓴 이유는 David B. Kirk이 다이렉트 X가 정한 것보다 더 높은 기능을 넣고 싶었기 때문이라고 밝힌 바 있습니다. 버텍스 쉐이더는 최대 64K 명령(다이렉트 X 9에선 최대 1K 명령) 지원, 삼각 함수의 지원, 픽셀 쉐이더도 다이렉트 X가 텍스처 32/컬러 64 명령만 지원하던 것이 최대 1K 명령까지 지원하는 등 기능이 크게 확장됐습니다. 또 16/32비트 부동소수점 연산도 지원합니다. 그 외에 보다 높은 데이터 밀도를 요구한 것도 이렇게 만든 이유입니다. 

 

문제는 이 당시에 겨우 0.13μm의 프로세스를 이용할 수 있게 되었기에 트랜지스터 수의 한계가 매우 큰 제약이 됐습니다.그래서 다기능 쉐이더를 기존 방식으로 구현하는 건 물리적으로 불가능해서 NV30 같은 방식밖에 없었다고 말할 수 있습니다. 그러나 이것만으론 아직 충분하지 않습니다. 예를 들어 128비트의 경우 제약이 있거나, 실제로는 32비트 연산 유닛이 아니라 16비트 연산 유닛으로 구성하는 대안도 있습니다. 이건 NV30이 아니라 NV35 세대의 이야기지만 NVIDIA는 분명 그 전에 이런 방법을 언급한 바 있습니다.

 

다만 결과적으로 이런 것들이 실패하게 되는 건 어쩔 수 없었다고 봅니다. 이상을 추구하다가 너무 앞질러 갔다는 걸 부정할 수 없습니다.

 

11.jpg

 

그래서 NVIDIA는 그 다음 세대인 지포스 6 시리즈, 즉 NV40에서 보수적인 구성으로 U턴합니다. 위 사진은 지포스 6800 울트라인데, 구체적인 내부 구조는 버텍스와 픽셀 쉐이더를 모두 32비트화하고 병렬로 구성하는 구조가 됩니다.

 

결국 힘들게 연구한 게 의미가 없다고 말할 수도 있겠는데, 매우 직접적인 구조를 사용하고 있습니다. NV30/35 세대에 새로 개발한 아키텍처를 썼다가 ATI R300/350 세대에서 패배한 이상, 처음부터 다시 시작한다는 의미에서 직접적인 구조가 필요하다고 판단했을 수도 있겠습니다. 다만 이 세대에서 이미 다이 크기의 비대화라는 패널티도 생기게 됩니다. 또 쉐이더의 수가 많아지면서 효율을 생각할 필요가 나온 시기이기도 합니다.

 

불행인지 다행인진 모르겠으나 NV40 이후엔 잠시 동안 정체기를 맞이합니다. 이건 NVIDIA가 PS3, ATI가 Xbox 360의 GPU 개발에 쫓겨 새 아키텍처를 투입할 여지가 없었기 때문입니다. 2005년에 NVIDIA는 G70 코어를 도입하지만 아키텍처는 NV40 그대로 제조 공정의 미세화(0.13μm → 0.11μm)와 쉐이더 수를 늘린 게 전부입니다.

 

다만 차세대 GPU 아키텍처에 대한 이야기는 여러가지가 나왔습니다. 그 대표적인 이야기는 GPU의 렌더링 처리에 대한 것으로, 쉐이더를 고속화해 온보드 DRAM에 접속할 때까지 레이턴시가 커지니 멀티 스레딩을 이용해 레이턴시를 줄인다는 것입니다.

 

펜티엄 4의 하이퍼 스레딩도 이와 비슷하지만 차이점이 있습니다. 하이퍼 스레딩의 주요 목적은 실행 유닛을 효율적으로 이용하는 것이며 레이턴시를 은폐하는 건 부차적인 목적인데, 이는 GPU와 반대입니다. 또 하이퍼 스레딩은 2 스레드를 동시에 실행하는데 GPU는 그보다 더 많은 스레드를 실행합니다. NV40의 경우 Fine-Grained Multithreading이란 이름의 멀티 스레딩이 있습니다.

 

아까 했던 이야기로 돌아가서, NVIDIA와 AMD가 각각 PS3와 Xbox 360에 신경쓰고 있을 동안 다이렉트 X 아키텍처의 개발은 천천히 이루어졌습니다. 결국 다이렉트 X 10으로 출시된 새 아키텍처는 지금까지의 픽셀/버텍스 쉐이더와 다르게, 통합형 쉐이더로 정해졌습니다. David E. Orton은 GPU가 단순히 렌더링 용이 아니라 범용을 위해 이런 구조를 썼다고 합니다. 단일 쉐이더의 성능은 어떻던 간에, 중요한 건 로드 밸런싱이 다이렉트 X 10 세대부터 이론적으로 가능하게 되며, 두 회사 모두 여기에 맞춰 다이렉트 X 10 세대의 아키텍처를 구축하게 됩니다.

 

 

다이렉트 X 10 세대의 통합형 쉐이더

 

12.jpg

 

통합형 쉐이더의 1세대 제품이 NVIDIA가 발표한 지포스 8000 시리즈입니다. 사실 NVIDIA는 G80을 발표하기 전엔 통합형 쉐이더에 부정적인 의견을 피력하는 등, 여러가지 교란 공작(?)을 폈으나 막상 뚜껑을 열어보니 통합형 쉐이더에 최적화된 구성을 썼지요. G80은 범용 GPGPU를 위한 구성을 갖췄으며 CUDA를 도입한 첫 제품이기도 합니다. 이로서 드디어 GPGPU를 위한 최소한의 환경이 갖춰진 것입니다.

 

이 G80 세대에선 하이엔드인 G80이 128개 스트리밍 프로세서(쉐이더)로 구성되는데, 이걸 CPU로 비교하면 128코어 멀티 코어가 됩니다. 다만 128개의 코어를 따로따로 관리하는 건 힘들기에 G*0은 우선 이 SP를 8개를 단위로 묶은 스트리밍 멀티프로세서(SM)라는 개념을 도입하고, SM을 2개씩 묶은 텍스처 프로세서 클러스터(TPC)를 도입하게 됩니다. TPC는 텍스처 유닛, L1/L2 캐시, 로드/스토어 유닛이 딸린 하드웨어의 관리 단위입니다.

 

아까 G80의 내부 구성에서 SP와 텍스처 유닛, L1 캐시를 넣은 구성이 8개 있는데 이게 바로 각각의 TPC가 됩니다. 하드웨어적으로 보면 G80 세대에선 이 TPC의 수를 조절해 다양한 제품을 만들고 있습니다.

 

소프트웨어적으로는 SM이 최소 단위입니다. SP는 기본적으로 스칼라 연산 유닛(1번에 1개의 데이터만 처리 가능)이 8개 모여 SP를 이루니까, 이론적으로는 8웨이 SIMD라 할 수 있습니다.

 

또 이 SM은 내부적으로 Warp라는 관리 단위를 이용합니다. Warp는 32 스레드 묶음으로 해석하면 되는데, 32개 스레드를 동시에 유지해 실행 가능한 스레드를 SP에서 가동시키기 위한 구조입니다. 앞에서 쓴대로 GPU 멀티 스레딩의 주요 목적은 레이턴시를 감추기 위한 것이며, Warp(에 포함되는 32스레드)가 실행 중일 때 메모리 액세스를 대기하는 등의 이유로 실행을 계속할 수 없게 됐을 때 다른 Warp(에 속하는 32스레드)를 실행하는 형태로 동작하게 됩니다.

 

이 Warp는 CUDA 프로그램에서 직접 나오는 개념은 아니지만, 이를 고려해서 프로그래밍을 하지 않으면 성능이 올라가지 않는다는 귀찮은 점이 있습니다. 또 Warp에 속하는 스레드는 전부 같은 명령을 실행해야 한다는 한계도 있습니다. 즉 32 스레드에서 병렬 처리를 한다고 생각하면 됩니다.

 

13.jpg

 

뒤이어 NVIDIA는 2007년 말에 G92 코어를 발표했는데, 제조 공정이나 구성은 물론 쉐이더의 구조는 거의 같습니다. 여기서 더 큰 변화를 이룬 건 2008년에 출시된 GT200 코어로, 위 사진은 지포스 GTX 280이 됩니다. 이 때의 아키텍처는 테슬라라고 부르는 게 더 편할지도 모르겠네요.

 

TPC/SM/SP이라는 구성은 변하지 않고, 내부적으로 Warp라는 개념을 사용한다는 건 변하지 않았지만(프로그래밍이라는 관점에선 큰 차이가 없음), 1개의 TPC에 포함되는 SM의 수가 2개에서 3개로 늘어났습니다. 제조 공정의 미세화했으니 SP의 수를 계속 늘리는 것도 가능했지만, 만약  G80 세대와 같은 구조로 하면 TPC의 수가 15개가 되면서 내부 배선이 힘들어지니 꺼렸던 것으로 보입니다.

 

또 다른 이유는 GPGPU적인 사용법이 점점 늘어나면서 I/O와 연산의 비율 중 연산이 중요해지며 TPC의 수를 늘리는 것 보단 TPC의 성능을 향상시키는 게 효율적이라고 판단했을 수도 있습니다. 이 때는 GPGPU적인 사용법이 점점 늘어나고 있던 시기입니다.

 

쉐이더 내부를 보면 GT200 세대에서 처음으로 배정밀도 부동 소수점 연산을 대응하게 됩니다. 배정밀도 연산은 GPU의 그래픽 연산에선 그리 많이 쓰지 않았습니다. 그건 지금도 마찬가지지요. 따라서 GPGPU를 위한 요소가 되겠습니다. 다만 이때는 기존의 SP를 배정밀도에 대응하는 회로 규모가 나오지 않아, 기존의 SP와는 별도로 배정밀도 연산 전용 유닛을 SM에 추가하는 구성이었습니다.

 

14.jpg

 

다만 이후 NVIDIA는 정체기에 들어갑니다. 정체라고는 해도 제조 공정 미세화와 이를 사용한 신제품의 출시는 수행했으나, 다이렉트 X 11의 대응은 AMD보다 늦었습니다. 이 다이렉트 X 11에 맞춰 내부 구조를 대폭 변경해 GPGPU용으로 강화한 것이 그 다음인 페르미 세대입니다.

 

SP의 이름은 CUDA 코어로 바뀌었고, 배정밀도 부동소수점 연산이 가능하게 됐습니다. 스루풋은 절반이지만. 1개의 SM은 8개의 SP에서 32개의 CUDA 코어가 되면서 구성이 4배로 늘었습니다. 또 다수의 Warp을 동시에 발행할 수 있는 구성이 되어 연상의 정확도가 높아졌습니다. 이를 둘러싼 주변 유닛을 대폭 강화한 결과, 테슬라 시절에 비해 명령 발행 효율을 크게 높인 것이 특징입니다.

 

다만 메모리 레이턴시를 멀티 스레딩만으로 은폐하기 어려워지면서, 기존의 CUDA 프로그램에선 성능이 잘 나오지 않는 경우도 있었습니다. 요컨대 L1/L2 캐시를 보다 잘 활용하도록 메모리 계층을 테슬라 세대보다 늘려, 이를 잘 활용하는 게 성능 개선의 핵심이라는 CPU에 더욱 비슷해진 형태가 됐습니다.

 

그 페르미의 1세대 제품인 GF100, 지포스 GTX 480은 물리 설계 때문에 성능 향상은 별로였고 수율도 나쁜데다 소비 전력까지 많은걸로 악명이 높았습니다. 아시는대로 하드웨어적으로는 멀티 코어 구성입니다. GPU로서 더욱 강력한 제품이 되야 했던 이 실패에서, NVIDIA는 경험을 헛되이 하지 않고 GF104를 내놓았습니다. SM의 구성을 GPU에 최적화하고 보다 높은 성능을 낼 수 있도록 해, 메인스트림에선 로직을 바꾸지 않고 물리 설계를 다시 해 GF100이 원래 내려던 성능을 내는 데 성공했습니다.

 

 

성능/전력 사용량의 효율을 중시한 설계로

 

다만 이 때부터 NVIDIA의 전략은 미묘하게 바뀝니다. 2010년 가을에 개최된 GTC의 기조 강연에서 NVIDIA는 페르미의 후속작으로 케플러와 맥스웰을 내놓을 것이라 밝혔지만, 순수하게 성능을 추구하는 게 아니라 성능/소비 전력이나 유효 성능을 중시하는 방향으로 전환할 것이라고 했습니다. 특히 맥스웰의 경우 현 시점에서 전망이 꽤 좋다고 할 수 있습니다.

 

15.jpg

 

케플러는 발표가 2012년으로 늦어졌지만 마이크로 아키텍처는 새로 바뀌었습니다. 이건 지포스 GTX 680이지요. CUDA 코어 자체는 여전히 스칼라 연산이지만 소비 전력을 낮추기 위해 파이프라인 스테이지를 줄였습니다. 또 스케줄링 기능을 소프트웨어(CUDA 컴파일러나 디스플레이 드라이버)로 옮겨 스케줄러를 간소화했습니다.

 

스케줄러를 간소화하면 보다 넓은 병렬 실행이 가능해집니다. 지금까지는 하드웨어 스케줄러가 병목 현상을 일으켜, 병렬도를 높여도 이용 효율이 올라가기 어렵다는 문제가 있었지만, 이제는 소프트웨어에서 사전 스케줄링한대로 병렬도와 효율을 모두 높이게 됐습니다. 그 결과 SM은 SMX로 확장되며 1개의 SMX에는 192개의 CUDA 코어가 탑재됩니다. 이렇게 해서 나온 GK110은 현재도 싱글 GPU 중 최고의 성능을 발휘하고 있네요.

 

이러한 설계 방침은 맥스웰에서도 계승되지만 맥스웰은 효율을 더 높이기 위해 다양한 개선이 이루어집니다. NVIDIA의 지난 10년 동안 GPU 아키텍처 변화는 여기까지 소개하겠습니다.

 

 

3. AMD 아키텍처의 변화

 

이번엔 ATI/AMD의 아키텍처 변화입니다. 앞서 말한대로 쉐이더를 실장하기 시작한 건 다이렉트 X 8의 세대이니, 다이렉트 X 9세대에 대해 이야기하기 전에 다이렉트 X 7~8 세대를 간단히 짚고 넘어갑시다.

 

다이렉트 X 7세대의 ATI 첫 제품은 라데온, 혹은 라데온 DDR, 라데온 7000 등 여러 버전이 있는데 모두 R100 코어를 쓰는 것입니다. 이 라데온 시리즈의 기초는 다이렉트 X 6 세대의 ATI 레이지 128 시리즈이며, 레이지 128은 Tseng Labs이 ET6300이라는 이름으로 개발을 거의 완료했던 물건으로 만들어졌는데, Tseng Labs는 ET6300의 완성 직전에 그래픽 부문을 통째로 매각해 이를 ATI가 인수해 레이지 128으로 출시했습니다. 레이지 128은 2개의 픽셀 파이프라인을 가진 제품인데 여기에 T&L(Transformation&Lighting) 유닛을 추가한 것이 R100 코어입니다. 물론 단순히 T&L을 추가한 것은 아니며 유닛을 픽셀 파이프라인 당 1개이던 걸 3개로 강화하는 등의 변경이 이루어졌습니다.

 

또 다른 특징은 레이지 128(보다 정확히는 ET6300)이 연산 유닛을 24비트 폭으로 만들었다는 것입니다. 이 결과 경쟁상대인 NVIDIA의 리바 128이나 지포스 128과 비교했을 때 16비트 컬러에선 성능이 크게 떨어지지만 24비트에선 같은 수준의 렌더링 성능을 실현할 수 있었습니다. NVIDIA처럼 16비트 연산기를 2개 구성해 32비트를 구성하지 않고 24비트를 유지한 건 ATI만의 스타일이라 할 수 있겠네요. 이 R100 코어에서 기능을 줄인 것이 RV200으로 픽셀 파이프라인은 1개입니다.

 

이후 R100을 다이렉트 X 8.1에 대응하도록 바꾼 것이 R200 코이이며 라데온 8500/9000/9200/9250이란 이름이 붙었습니다. 다만 이 시기 ATI는 R300 세대를 앞당기는 데 주력하고 있었고, 칩셋 사업에 참가하기 위해 IGO 모델을 개발하느라 바빴기에 R200에서 큰 변화는 없었습니다. 여기에 픽셀 파이프라인이란 말을 쓰기엔 라는 적합하지 않으니 쉐이더의 수를 놓고 보면-

 

R100과 R200의 스펙
픽셀 쉐이더 버텍스 쉐이더 텍스처 유닛 ROP
R100 4 0 6 2
R200 8 2 8 4

 

같은 식으로 R100의 2배에 달하는 쉐이더를 탑재함과 동시에, 다이렉트 X 8.의 쉐이더 모델 1.4를 지원하는 것이 주요 차이입니다. 앞서 말한대로 쉐이더 모델 1.4는 다이렉트 X 9의 쉐이더 모델 2.0의 선행 확장같은 느낌이 큽니다. 그런 의미에서 R200은 이후 나오는 R300의 과도적인 모델이라 부를 수 있겠습니다.

 

다음은 다이렉트 X 9 세대의 R300입니다. R300 세대는 ATI가 2000년에 인수한 ArtX 개발 팀의 첫 제품이라고 할 수 있습니다. 그리고 이 ArtX의 CEO 겸 사장이었던 Dave Orton은 ATI의 COO(나중에 CEO)가 되어, AMD에게 인수될 때까지 회사를 이끌어 왔던 것만 봐도 R300이 ATI에게 중요한 제품이었음을 알 수 있습니다.

 

다이렉트 X 9세대 GPU의 구조는 R300의 구조와 큰 차이가 없어 보입니다. 물론 이것은 큰 관점에서 봤을 경우의 이야기며 내부적으로는 여러 장치가 추가됐습니다. 예를 들면 최대 256칩까지 평행 연결될 수 있으며, 픽셀 쉐이더의 기능을 하드웨어가 아닌 마이크로 코드로 구현할 수 있습니다. 이 때는 GPU가 GPGPU로 퍼져나갈 것인지, GPU에 오프라인 렌더링 같은 요소가 필요로 하는지 아직 확인되지 않은 시기이기도 합니다. 가능한 걸 우선 넣어두고 앞으로의 동향을 살펴본다는 것이지 싶습니다.

 

다만 R300 자체는 최신 공정(0.15μm)과 256비트 메모리로 2002년에 뽑을 수 있는 최대한의 구성을 썼으며, 트랜지스터 수는 1.1억개에 달합니다. 또 쉐이더 내부는 NVIDIA와 달리 128비트 SIMD 구성을 써 멀티스레드가 이루어졌다고 볼 수 있지만 효율은 그리 높지 않은 것으로 평가됐습니다. 이건 이론을 그대로 구현하려 해도 효율은 높지 않으니 성능을 더 뽑기 위해선 어쨌던 덩치를 키워야 한다는 이야기가 됩니다.

 

현실적인 문제로 0.15μm 프로세스에서 쉐이더 수를 늘리는 건(트랜지스터 수를 늘리는 건)은 제품 수율 때문에 무리이니 0.13μm로 이행이 불가피해 보였습니다. 그러나 실제로는 마이너 체인지 한 R350 세대에서도 계속 0.15μm를 유지했습니다. 아키텍처적으로 볼 때 F-Buffer의 탑재 같은 확장은 있지만, 오프라인 렌더링은 논외로 치고 실시간 렌더링의 경우 R350과 R300이 거의 차이가 없었습니다. F-Buffer는 굳이 말하자면 오프라인 렌더링도 가능한 것이며, 실시간 렌더링의 경우 어디까지나 다이렉트 X 9가 요구하는 범위에 두고 있습니다.

 

17.jpg

 

ATI는 뒤이어 R400이란 코어를 개발하고 있었습니다. 최소한 2003년 5월 시점까진 R400과 그 후속작인 R500 코어가 로드맵에 있었는데, 2003년 9월에 모두 취소되고 R420을 쓴 라데온 X800T가 등장하게 됩니다.

 

그 이유는 많지만 그 중 상당수가 PCI-E를 지원하기 위해서입니다. 2004년엔 AGP에서 PCI-E로 전환이 시작되면서 시장에서 두 플랫폼이 모두 유통괴고 있었습니다. 당시에 PCI-E를 구현하려면 그 때 제조 공정에서 매우 부담스러운 다이 크기가 필요했습니다. 그게 어느 정도인고 하면 S3가 PCI-E를 위해선 픽셀 파이프라인을 4개에서 2개로 줄이지 않으면 어렵다고 말했을 정도입니다. 저가형 제품에서 쓰는 다이 크기는 더욱 줄어드는데, 이는 픽셀 파이프라인을 줄이지 않으면 작은 다이에 들어가지 않을 정도로 해당 부분이 컸다는 소리입니다.

 

그래서 NVIDA와 ATI는 GPU는 그대로 AGP로 나오면서 AGP to PCI-E 브릿지 칩을 별도로 장착하는 방법을 내놓았는데, NVIDIA가 하이엔드 제품까지 이를 그대로 지킨 데 비해 ATI는 R420에서 PCI-E와 AGP 모두를 네이티브 지원하는 제품을 내놓았습니다. 그러나 그 결과 R420은 성능이 R360의 두배가 됐지만 내부 아키텍처 자체는 R360과 크게 다르지 않았는데, 이는 제조 공정이 겨우 안정된 TSMC 0.13μm와 0.11μm로 이행하면서 가능해졌습니다.

 

18.jpg

 

이후엔 ATI도 범용 쉐이더를 사용해 GPGPU 요소를 더하는 필요성을 느끼게 됩니다. 다만 R450은 취소하고 R480을 쓴 라데온 X850을 2004년 12월에 발표합니다. 제조 공정이나 내부 구조는 거의 변하지 않고 코어/메모리 클럭만 살짝 오른 마이너 업데이트 제품입니다. 따라서 소비 전력도 늘었고 레퍼런스 카드도 듀얼 슬롯이 됐지요. 이건 AMD의 생각대로 되지 않았다는 겁니다.

 

이건 NVIDIA도 마찬가지인데, ATI는 Xbox 360 전용 R500 기반 커스텀 GPU 코어를 내놓고, NVIDIA는 PS3에 G70의 파생형인 RSX를 내놓는 작업에 열중하느라, 2005년까지 커다란 움직임이 생길 수가 없었습니다. 이후 제품이 나올 수 있게 된 건 Xbox 360이나 PS3를 위한 작업이 끝나고 난 뒤의 일입니다.

 

그리고 2005년 10월에 ATI는 R520, 라데온 X1800 XT를 발표합니다. 쉐이더 모델 3.0을 지원하는 제품으로 통합 쉐이더는 다이렉트 X 10으로 미룬 셈이지요. 하지만 GPGPU를 의식해서인지 통합형 쉐이더를 염두에 둔 구성을 씁니다. 픽셀 쉐이더는 이 때도 16개로 R400과 크게 달라지지 않았지만, 내부 접속을 링 버스로 하는 것과 동시에 메모리를 32비트 단위로 바꾸고 512비트 멀티스레딩(ATI는 울트라 스레딩이라 표현)을 구현하는 등 내부를 극적으로 바꿨습니다.

 

이러한 변화는 R520의 성능을 생각하면 사치스러운 구성이나, 이는 그 다음의 T580 세대에서 픽셀 쉐이더를 3배(16개에서 48개)로 늘리면서 앞으로를 염두에 둔 포석임이 드러나게 됐습니다. R580이 R520에 비해 20% 정도의 트랜지스터 수 증가로 100%의 성능 향상을 실현한 것이 가능한 이유는, R520이 나왔을 때 이미 R580의 규모를 충분히 받춰줄 기반을 다져 둔 덕분이라 할 수 있겠습니다.

 

덧붙여서, R520 새데에서 ATI는 다이렉트 X 10의 통합형 쉐이더 필요한 핵심 기술을 거의 다 넣었습니다. 사실 Xbox 360에 들어간 R500 기반 커스텀 GPU 코어는 통합형 쉐이더 구성을 사용하는데, 여기서 어느 정도 확인한 후 필요한 기술을 확장해 R520/R580에 넣어 동작을 보고, 그 다음인 R600에서 통합 쉐이더로 건너간다는 시나리오를 세웠던 것이고, 실제로도 그 시나리오는 잘 실행됐다고 생각할 수 있겠습니다.

 

 

AMD 인수로 방향을 전환

 

이야기가 다른 방향으로 흘러가기 시작한 건 AMD가 ATI를 인수하면서부터입니다. 원래 이 때 AMD는 코프로세서를 구상하고 토렌지 이노베이션 소켓을 내놓을 움직임을 보였으나, ATI를 인수하면서 코프로세서의 상당 부분이 AMD에게 들어가게 된 것입니다. 코프로세서에 대한 건 나중에 이야기하고, 여기선 그게 GPU에 미친 영향을 설명하겠습니다.

 

원래 ATI는 하이엔드 제품의 경우 NVIDIA를 넘어설 정도로 거대한 다이를 만들고 있었습니다. 이것은 R500 세대도 마찬가지였으며 그 결과 R520은 90nm 공정을 이용한 3억 2100만개 트랜지스터로 280제곱mm의 다이라 나온 반면, R580은 80nm 공정을 이용해 3억 8400만개의 트랜지스터로 352제곱mm의 다이가 나왔습니다. 그 다음인 R600은 통합 쉐이더를 탑재할 뿐만 아니라 쉐이더의 수도 압도적으로 늘어나 65nm 공정으로 만들 수밖에 없다고 보여졌습니다.

 

그런데 라데온 HD 2900이란 이름으로 2007년 5월에 등장한 R600 코어는 80nm 공정으로 통합 쉐이더를 320개 탑재한 몬스터가 됐습니다. 트랜지스터 수는 7억개며 다이 크기는 408제곱mm에 달합니다. 이는 원래 R600의 설계가 AMD에게 인수되기 전에 끝난 것이며, 그 시점에선 아직 65mm 공정의 설계가 이루어지지 않았던 것으로 보입니다. 대신 R600의 저가형인 RV610/RV630 코어는 65nm 공정을 씁니다.

 

19.jpg

 

 

R600, 라데온 HD 2900XT는 R500에 비하면 많은 새 기능을 탑재한 의욕적인 제품이지만, 그 보다 더 큰 영향을 준 것은 쉐이더를 기존의 128비트 SIMD에서 5웨이 VLIW(VLIW5)로 바꾼 것입니다. 당시엔 이것이 병렬도를 높이는 데 효과적이라고 판단한 것에서였습니다. ATI도 GPGPU적인 사용법을 모색하면서 다양한 명령을 쉐이더에서 처리할 필요가 있다고 생각해, 이를 최소한의 비용(최소한의 트랜지스터 수)로 구현하려면 VLIW가 효과적이라고 판단한 듯 합니다. 그래서 32비트 ALI를 Warp를 사용해 묶는다는 선택을 했고 이것이 NVIDIA 아키텍처와 주요 차이가 됩니다. R600에선 320개의 쉐이더라 표기하지만 이는 1개의 VLIW5를 5쉐이더로 친 것이며 VLIW 셋트로 따지면 64개니 R580보다 크게 늘어난 것도 아닙니다.

 

20.jpg

 

전환점은 그 다음인 RV670, 라데온 HD 3870에서 나타났습니다. RV는 앞서 말한대로 하이엔드가 아니라 메인스트림, 보급형에 붙는 코드네임인데, 라데온 HD 3000 시리즈는 RV670, RV635, RV620, RV610처럼 RV 시리즈가 대부분이며 유일하게 라데온 HD 3870 X2에만 R680이라는 이름이 붙어 있습니다. 라데온 HD 3870 X2는 RV670이 2개 붙은 제품이니 GPU라기보다는 보드의 모델명에 가깝지요.

 

라데온 HD 3870는 기라데온 HD 2000의 제조 공정을 바꾼 것에 해당하는 버전으로 다이렉트 X 10.1을 지원하는 것 외엔 내부 변화는 거의 없습니다. 트랜지스터 수는 약간 줄어 6억 6600만개가 됐지만 다이 크기는 대폭 줄어 190제곱mm이 됐습니다. 메모리 버스도 256비트로 낮춰 GPU 제조 원가와 그래픽카드 제조 원가를 모두 낮추는 데 성공했습니다. 당시 AMD는 거대한 다이를 높은 클럭으로 작동시키는 건 수율이나 소비 전력에서 모두 적합하지 않다고 인식하고 있었으며, 여기에 따라 제품의 성격을 이렇게 바꾸게 된 것입니다.

  

AMD는 당시 CPU 사업이 결코 좋다고는 말할 수 없는데다가 ATI를 인수하느라 지출한 비용이 상당했습니다. 반면 ATI의 그래픽 사업은 순조로왔으며 수익도 제대로 나오고 있었습니다. 그래서 ATI의 매출과 수익율을 높이고 AMD 본사의 재무 상황을 개선하기 위해 개발비나 생산 비용이 많이 들어가는 큰 다이의 GPU에서 철수하고 적당한 크기의 다이(2007년엔 200제곱mm 정도)를 내놓는 것이 위험 부담을 줄이고 수익을 최대화하는 방법인 것입니다.

 

21.jpg

 

이 전략은 이후에도 계속 이어집니다. 2008년엔 라데온 HD 4000 시리즈가 나오는데 여기도 코어 코드네임은 RV770으로 계속해서 RV 시리즈를 쓰게 됩니다. 위 사진의 라데온 HD 4870은 55nm 공정을 계속 사용하며 트랜지스터 수는 9억 5600만개까지 늘었으나 다이 크기는 256제곱mm로 아직까진 적당한 편이었습니다. 내부 구조는 VLIW5 쉐이더를 계속 사용하면서 그 수를 160개(AMD의 계산 방식대로라면 800개)로 늘렸습니다.

 

한편 링 버스를 일반적인 크로스 바 스위치로 대체하고 NVIDIA보다 먼저 GDDR5 메모리를 채용해 메모리 버스를 늘리지 않으면서 메모리 대역을 높여 전체 성능과 효율을 늘렸습니다. 링버스를 없앤 건 텍스처 캐시의 구성을 바꾸니 링버스 자체가 불필요해졌다는 이유에서입니다. 링버스는 확장성을 확보하려면 좋은 선택이며 인텔은 샌디브릿지 이후 내부 버스를 링버스를 씁니다. R520에서 링버스를 쓴 것도 그런 이유에서겠지만 앞으로 거대한 다이를 만들 계획이 사라지니 일반적인 크로스 바 스위치로도 충분하리라고 판단한 것입니다.

 

22.jpg

 

뒤이어 등장한 다이렉트 X 11 세대의 첫번째 카드, Cypress 라데온 HD 5800 역시 그 전략의 연장선상에 있습니다. 쉐이더의 기본적인 구조는 계속해서 VLIW5를 지키면서 다이렉트 X 버전을 올린 걸 빼면 큰 차이가 없습니다. 전체적으로 보면 RV770의 듀얼코어라 할 수 있으며 트랜지스터 수는 21억 5천만개로 늘어났지만 40nm 공정을 사용해 다이 크기는 334제곱mm로 그렇게 크진 않습니다. 2.72TFLOPS에 달하는 처리 성능은 이 때 분명 최고 성능이라 할 수 있었습니다.

 

오히려 AMD는 이렇게 높은 연산 성능을 쓸만한 API가 보급되어 있지 않다는 게 문제였습니다. CUDA의 보급이 순조롭게 진행되던 NVIDIA와 좋은 대조를 이루고 있습니다. 2007년부터 AMD는 Brook+이라 불리는 GPGPU용 라이브러리를 제공하고 있지만 전혀 보급되지 않았습니다. 따라서 아무리 연산 성능이 좋아도 도통 써먹을 곳이 없는 것이지요.

 

그러다가 2008년에 OpenCL 1.0이 출시되고(이것은 애플의 맥 OS X 위주입니다). 뒤이어 더욱 범용으로 쓸 수 있는 플랫폼을 목표로 한 OpenCL 1.1의 책정이 시작됩니다. 또 마이크로소프트도 GPGPU API로 DirectCompute을 책정합니다. 이러한 API에 의해 CUDA에 대항할 수 있다고 판단한 AMD는 우선 OpenCL에 주력하며 Cypress에서는 이러한 OpenCL을 최대한 지원하는 하드웨어 구성을 갖춰 GPGPU 시장에서 NVIDIA를 추격할 준비를 하게 됩니다.

 

23.jpg

 

AMD는 다음 제품에서 32nm 공정으로 미세화할 것이라 예측했지만 TSMC의 32nm 공정은 개발에 어렴움을 겪다가 결국 취소됐고 이후의 28nm 공정이 나올 때까지 1년이 비게 됐습니다. 이 틈을 이용해 쉐이더를 재설계한 것이 코드네임 Cayman, 라데온 HD 6970입니다. 이 때 이미 GCN의 설계를 해 둔것 같지만 GCN을 쓰지 않은 건 40nm 세대에서 GCN을 써도 충분한 성능이 나올 것이라고 보진 않은 이유에서로 보입니다.

 

Cayman은 쉐이더 구성을 4웨이 VLIW(VLIW4)로 전환했습니다. 이렇게 한 가장 큰 이유는 명령 병렬도를 낮춰 코어 가동율을 높이기 위해서입니다. 제조 공정이 40nm를 유지하는데 다이 크기를 늘리면 적절한 다이를 만든다는 전략에 어긋납니다. 그럼 효율을 높이는 수밖에 없지요. 다만 이것은 종류나 사용법을 지켜 보면서 최적화하는 것이니 유연성은 사라지게 됩니다. 허나 Cayman은 다음 세대로 가는 징검다리 역할을 하니 나쁘지 않지요. 이 VLIW4는 트리니티와 리치랜드까지 이어지면서 개발 비용을 나름 잘 뽑은 셈이 되겠습니다.

 

2011년에 AMD는 GCN(Graphics Core Next) 아키텍처를 발표합니다. 분산 처리 모델로 바뀌고 명령 발행이 CU(Computation Unit)으로 옮기면서VLIW를 버리고 SIMD로 전환하는 등 내부 구조가 크게 바뀐 것이 특징입니다. 이런 변화의 가장 큰 목적은 HSA(Heterogeneous System Architecture)와 친화성이 높고 GPGPU를 쓰기 쉽다는 것입니다. 이 때인 HSA가 없어서 FSA(Fusion System Architecture)라고 했지만요.

 

24.jpg

 

이 GCN을 처음으로 쓴 것이 코드네임 타히티, 라데온 HD 7900 시리즈입니다. 그 내부 구조는 NVIDIA의 SM(Streaming Multiprocessor)와 비슷한 점도 있지만 GCN은 HSA를 위해 hQ라는 요소를 넣었습니다.

 

카베리에서 CPU 코어와 GPU 코어를 동급으로 다루는 큐 시스템이 처음으로 구현됐습니다. 이로서 CPU/GPU의 태스크 오프 로딩과 연계가 매우 쉬워졌으나 이를 위해서는 GPU에서 CPU의 명령을 해석하고 실행할 수 있지 않으면 안 됩니다. 또 GPU 전체에서 1개나 2개의 프로세서 엘리먼트만 존재한다면 그 크기가 너무 커 효율이 나빠집니다. CU라는 구조는 HSA의 최적화된 모습을 그리고 거기에 딱 맞는 연산 성능과 정확도를 감안해서 결정한 스펙입니다.

 

그 결과 타히티를 비롯해 모든 AMD의 GPU와 대부분의 APU인 GCN이 채용됐지만, 마이너 체인지나 연산 이외의 부분(트루 오디오의 지원이라던가)에 차이는 있어도 CU 자체는 같은 것을 씁니다. 그 결과 요구하는 성능에 맞춰 CU의 수나 클럭만 조절하는 형태로 제품 라인업이 구성된 게 현재 AMD의 상황입니다.

 

 

4. CPU와 GPU의 연계

 

마지막으로 이번엔 CPU와 GPU의 연계에 대해 설명하겠습니다.

 

GPU가 그저 2D 그래픽 출력만 담당하던 시절에는 CPU와 GPU 사이의 연계를 생각할 필요가 별로 없었습니다.

 

이건 GPU가 출력 전용 장치니까, CPU는 단순히 렌더링 명령을 GPU로 넘기면 끝나고. CPU가 받은 건 최종적으로 렌더링이 끝난 명령의 완료 통지 뿐이었습니다. CPU는 GPU에서만 처리하는 렌더링 명령을 만들고 끝나면 정리하기만 하면 됩니다. 따라서 GPU는 이렇게 받은 처리를 얼마나 빠르게 끝내는지, CPU의 부하를 어떻게 하면 줄이는지가 중요할 뿐이었는데, 이 중 두번째 이유가 2D 렌더링 가속기로 구현된 요인이 됩니다.

 

그러나 3D가 되면서 조금 이야기가 달라졌습니다. 렌더링 명령 외에도 3D의 폴리곤 표면에 붙이는 텍스처 데이터가 필요했기 때문입니다. 이 텍스쳐 데이터는 경우에 따라서 데이터 양이 매우 많아지게 됩니다. 그래픽카드의 내장 메모리로선 부족할 수도 있고, 실시간으로 처리해 임의의 텍스처를 붙이니 이걸 CPU에서 관리하는 건 어려우며 처리가 느려질 수도 있었습니다.

 

그래서 인텔이 주장해 개발한 것이 AGP입니다. 텍스처 자체는 시스템 메모리에 저장하지만 필요에 따라 GPU에 DMA(Direct Memory Access)를 통해 고속으로 전송하겠다는 발상으로 만든 것입니다.

 

최초의 AGP 1X의 전송 속도는 266MB/sec로, 이후 2X에서 533MB/sec, 4X에서 1.06GB/sec, 8X에서 2.13GB/sec까지 전송 속도는 높아졌지만, 재밌는 건 이 속도는 어디까지나 CPU(보다 정확히 말하면 시스템 메모리)→ GPU로 가는 속도이며, 반대로 GPU→ CPU로 가는 전송 속도는 1X~8X가 모두 266MB/sec로 고정됐다는 겁니다. 따라서 CPU→ GPU의 속도가 중요하지 그 반대는 크게 중요하지 않다는 이야기가 됩니다.

 

그런데 이게 효과가 있었냐면 거의 없었습니다. AGP가 등장한 건 1996년의 일인데, 이 시기의 대표적인 그래픽카드인 리바 TVT의 경우 AGP 2X를 지원하며 내장 메모리의 대역폭은 880MB/sec입니다. 반면 AGP 4X를 지원하는 리바 TNT2의 경우 대역폭이 2.4GB/sec에 이르러 AGP 전송 속도의 2배 이상이 됩니다. 비디오 메모리도 리바 TXT에서 8~16MB, 리바 TNT 2에서 16~32MB가 되니 당시 3D 게임의 텍스처를 저장하기에 충분한 크기였지요.

 

이는 다음 세대도 마찬가지입니다. 3D 게임이 필요로 하는 메모리의 용량에 맞춰 비디오 메모리를 늘리게 됩니다. 반대로 비디오 메모리의 증가에 맞춰 게임이 사용하는 메모리를 늘렸을 수도 있겠지만. 그 결과 AGP는 3D 게임을 불러올 때 텍스처를 가져오는 용도로만 쓰며, 게임 중에 AGP를 통해 새로운 텍스처를 가져오는 일은 별로 없었습니다. 이것은 이후 AGP 8X에서 PCI-E 1.0으로 바뀌면서, 이론적인 대역폭이 두배로 늘어났음에도 불구하고(AGP 8X는 2.13GB/s, PCI-E 1.0 x16은 4GB/s) 게임 성능에 아무런 영향도 주지 않았음을 보면 짐작이 됩니다.

 

사실 이러한 상황은 현재도 크게 다르지 않습니다. 예를 들면 SLI나 크로스파이어를 구성할 때 PCIe x16이 아닌 PCIe x8+x8, 혹은 PCIe x8+x4+x4구성에서 연결하거나, 슬롯 모양은 x16이지만 내부 신호는 x1만 들어가는 메인보드를 사용해도 성능 하락이 그리 크지 않다는 걸 보면 알 수 있습니다. 따라서 GPU에서 렌더링을 시작하면 일일이 통신을 하지 않는다는 것이 됩니다.

 

결과적으로 말하면 인터페이스의 속도는 렌더링을 시작하기 전에만 영향을 주며, 그렇기에 3D 렌더링의 경우 CPU와 제휴를 할 의미가 별로 없게 됩니다(AMD의 맨틀은 또 다른 이야기입니다). 물론 데이터나 픽셀 수, 폴리곤, 텍스처 등의 절대적인 용량이 1996년부터 엄청나게 늘어나고 있어, 지금은 나름대로 빠른 인터페이스가 필요하긴 하지만, 여전히 CPU와 GPU는 어떤 의미에선 독립해서 움직이고 있다고 말할 수 있겠습니다.

 

이런 상황이 달라지게 된 것은 GPGPU적인 요소가 나오면서부터입니다. GPU로 사용할 때는 연산 결과(최종적으로 생성한 영상)을 CPU로 되돌릴 필요가 없었지만, GPGPU로 사용할 때는 연산 결과를 다시 CPU로 보내야 합니다. 따라서 먼저 GPU→ CPU의 전송 성능을 올려야 합니다. 다행히도 AGP에서 PCI-E로 바뀌면서 CPU와 GPU의 전송 성능은 양방향이 모두 같은 수준을 지키게 됐습니다.

 

이후엔 PCI-E의 속도가 느리다는 이야기가 나오게 됩니다. 여기엔 2가지 이유가 있는데 먼저 절대적인 대역폭이 있습니다. 최초의 GPGPU 제품인 NVIDIA C870의 경우 최고 430GFLOPS의 성능을 냅니다. 아주 단순하게 계산해서 1FLOPS=32비트(4바이트)의 결과가 나온다고 해도 최고 1.27TB/s의 데이터가 만들어진다는 겁니다. 물론 비디오 메모리에서도 이 정도의 대역은 나오지 않습니다(최고 76.8GB/s). 따라서 연산 효율이 떨어질 수밖에 없는데, 내장 비디오 메모리도 1.5GB밖에 안 되니 이걸 다 쓰면 PCI-E를 통해 시스템 메모리로 보내지 않으면 안 됩니다. 이 때의 대역폭은 PCI-E 1.0의 4GB/s밖에 안되지요.

 

즉, 어느 정도 용량이 컨 데이터를 계산한다면 430GFLOPS는 고사하고 1GFLOPS 정도의 성능만 나오게 됩니다. 이런 대역폭의 병목 현상은 지금도 계속 존재하는 문제입니다. PCI-E 2.0에서도 8GB/sec니까 2GFLOPS, 3.0에서도 16GB/sec니까 4GFLOPS 정도밖에 되지 않는 것입니다. 그래서 이걸 극복하기 위해 프로그램을 기록하는 방법을 달리 해서 전송을 줄이게 됩니다. 예를 들면 아래 그림처럼 Y=AX^2+BX+C라는 계산을 GPU에서 할 때는-

 

1.A와 X를 전해 AX의 2제곱을 계산
2.B와 X을 주고 BX를 계산
3. 이를 CPU에서 정리하고 Y를 산출

 

같은 식으로 하지만, 이 경우 CPU의 계산량이 많아지고 빈번하게 데이터의 전달이 발생하게 됩니다.

 

그래서 처음에 A/B/C/X를 다 주고 모든 계산을 GPU가 하며 마지막의 결과만 받도록 하면 전송에 걸리는 오버 헤드가 대폭 줄어듭니다. 또 아래 그림에선 전송보다 계산에 시간이 더 걸리는 것처럼 그려졌으나 실제로는 계산보다 전송에 시간이 더 걸립니다. 얼마나 전송을 줄이고 정리해서 GPU가 계산하도록 하는지가 GPGPU 프로그램에서 중요하며, 이는 지금도 변함이 없습니다.

 

25.jpg

 

데이터 전송량을 줄이는 연구

 

다른 건 동기화가 느리다는 겁니다. 아래 그림처럼 CPU가 여러 스레드(NVIDIA나 AMD가 말하는 스레드가 아니라 프로그램 언어의 스레드)를 GPU에서 실행한다고 가정합시다. 이런 방식에서 모든 GPU의 스레드에 같은 부하를 줘 특정 스레드가 장시간 동작하는 사태를 피하도록 하지만, 비디오 메모리에 액세스가 집중하면서 스레드에 따라 메모리 액세스의 대기 시간이 길어져 처리 시간이 늘어날 수 있으니 각 스레드마다 종료 시간은 차이가 납니다.

 

26.jpg

 

스레드 대기 시간

 

연산이 끝나면 CPU에 태스크 종료 통지를 하지만 PCI-E는 이 통지를 보내는 데 부하가 크고 느리다는 문제가 있습니다. 여기에 명확한 답을 가지고 온 건 인텔입니다. 2007 IDF 베이징의 설명회에서 Geneseo란 이름의 PCI-E 전용 확장을 발표한 것인데, PCI-E의 통지나 동기에 들어가는 오버헤드를 줄이겠다는 것으로, 현재 PCI-E 2.1로 표준화가 됐습니다. 그런데 지금의 GPGPU가 모두 이걸 쓰냐고 묻는다면 그것도 아닙니다. 오히려 인텔도 제온 파이에선 이걸 지원하지 않고, AMD와 NVIDIA도 이를 사용하려는 적극적인 움직임을 보이지 않습니다.

 

 

GPGPU에서 중요한 CPU-GPU의 통신

 

여기서부터가 본론입니다. CPU와 GPU의 연계에서 먼저 움직인 건 AMD입니다. AMD가 ATI를 인수한 건 그저 GPU 코어를 넣기 위해서가 아니라, 앞으로 가속 장치로 GPU를 쓰는 걸 염두에 둔 행보였습니다. 실제로 인수 직전에 나온 인터뷰를 봐도 그런 계획을 확인할 수 있는데요. 그 때 Phil Hester(2013년 9월에 사망)는 "앞으로 더욱 긴밀한 통합이 있을 수도 있다"고 말하면서 아래 그림과 같은 이야기를 했습니다.

 

27.jpg

 

바로 CPU 안에 GPU(쉐이더)를 포함시키는 것입니다. 이건 어디까지나 CPU 입장에서 본 GPU이며, GPU는 셋업 박스, 스케줄러, 디스패처 같은 유닛을 따로 넣는 식으로 구상했을 수 있겠으나 이건 알 수 없으며 그리 중요하지 않습니다. 여기서 중요한 건 CPU와 GPU가 데이터 교환과 동기화, 메모리 공유를 매우 쉽게 수행할 수 있는 구조를 도입하겠다는 것입니다.

 

AMD가 2007년에 발표한 SSE5는 그 좋은 예가 되겠습니다. 16비트 부동소수점 연산이나 FMA(Fused Multiply Accumulate)명령 등은 GPU와 데이터 교환을 전제로 한 포맷이라 해도 과언이 아닙니다. 최종적으로 AMD는 SSE5를 포기하고 AVX 호환으로 가게 되지만 확장 명령으로 XOP/CVT16/FMA4를 새로 정의했습니다. 이건 GPU와의 데이터 교환을 계속 중시하고 있는 것이라 봐도 좋습니다. 다만 위 그림대로 구성하려면 CPU와 GPU 모두 기술적인 도전이 많이 필요하니 이보다 더욱 현실적인 노선으로 갈 필요가 있었습니다.

 

이 '현실적인 노선'은 외장 그래픽(Discrete GPU)의 통합을 포기한다는 것도 포함되어 있습니다. 앞서 말한대로 느린 동기화 속도를 어떻게 해결한다 한들 대역폭의 부족은 보충할 방법이 없기 때문입니다. 뒤에서 말하겠지만 메모리 스페이스를 공유할 수 있도록 하면서 캐시 일관성을 지키기엔 PCI-E는 너무 느립니다. 그래서 AMD는 내장 그래픽에서 CPU와 GPU를 통합을 추진하기로 합니다.

 

여기서 AMD는 잠시 고민하게 됩니다. 2008년 말에 발표된 로드맵에서 APU라는 이름을 쓰는 첫 제품이 나오는 건 2011년이라고 예고했는데요. 첫 실리콘의 발표는 2010년의 컴퓨텍스가 됩니다. 이 때 나온 라노는 CPU와 GPU가 하나의 다이에 탑재되고 메모리 컨트롤러를 공유한다는 게 주요 특징이지만, 이를 뒤집어서 보면 특징이 그것밖에 없다는 말도 됩니다. 내부 구조에서 가장 큰 특징은 어니언과 갈릭이라는 2종류의 내부 버스를 같이 쓴다는 것이 되겠습니다.

 

퓨전이란 이름으로 통합 계획을 짠 CPU와 GPU는 최종적으로 OpenCL을 기반으로 한 HSA(Heterogeneous System Architecture)라는 형태로 통합됩니다. OpenCL은 위 그림에 나온대로 명령어 집합 수준보다 더 큰 틀에서 처리하는 분산 구조입니다. HSA의 핵심은 HSAIL라고 불리는 중간 언어로 여기서 하드웨어의 차이(CPU와 GPU)를 흡수합니다. 그 요점은 HSAIL을 이용해 애플리케이션적으로 CPU와 GPU의 차이가 사라지는 것이 됩니다.

 

이렇게 하면 그 동안 해왔던대로 GPGPU를 PCI-E 경유로 가속기로 사용하게 되면 효율이 나빠집니다. 우선 메모리 문제가 있습니다. PCI-E를 거치면 GPU는 어디까지나 I/O 디바이스로 취급하며 그 경우 GPU가 액세스할 수 있는 메모리 스페이스에 한계가 있습니다. 아래 그림은 물리 메모리가 프로그램(프로세스)에 할당되는 메모리 스페이스와 I/O 디바이스에 할당되는 I/O 스페이스라는 2개로 분할됨을 설명합니다.

 

28.jpg

 

CPU와 GPU가 액세스할 수 있는 영역입니다. CPU는 양쪽 모두에도 액세스할 수 있지만 GPU는 오직 I/O 스페이스에만 액세스할 수 있는 문제가 있습니다. 그럼 프로세스도 I/O 스페이스를 이용해 프로그램을 실행하면 되지 않냐고 할 수 있겠으나, 원래 이 영역은 I/O 디바이스와 통신용으로 마련한 특수 영역이라 프로세스에서 액세스는 가능하지만 본래의 메모리 스페이스와 똑같이 취급하진 않습니다. 따라서 원래 방식에서는-

 

1. CPU가 모든 데이터를 메모리 스페이스에서 I/O 스페이스로 복사
2. I/O 스페이스에 GPU가 액세스해 처리하고 I/O 스페이스에 결과를 재기록
3. CPU가 결과를 I/O 스페이스에서 메모리 스페이스로 복사

 

-라는 귀찮은 절차를 밟아야 했습니다. 그런데 HSA 환경은 이렇게 CPU가 끼어들 필요가 없이 GPU가 직접 메모리 스페이스에서 데이터를 불러오고 결과를 저장할 수 있는 걸 전제로 한 것입니다. 그렇지 않으면 오버헤드가 너무 커져 곤란해지기 때문입니다. 그래스 기존의 접근 방식에 덧붙여 직접 메모리 스페이스에 액세스할 수 있는 기능을 GPU에 추가해야 하는데, 여기서 문제가 되는 건-

 

페이지 폴트 기능의 추가

캐시 일관성 유지 기능 추가

 

-가 됩니다. 우선 페이지 폴트를 봅시다. 어떤 프로세스가 있는 가상 어드레스에 CPU 코어가 접속하려 하고, 그 가상 어드레스가 물리 메모리에 매핑 되지 않았을 경우, CPU는 페이지 폴트 인터럽트를 발생시킵니다. 이에 따라 OS가 그 가상 어드레스에 물리 메모리를 할당하며, GPU도 이와 같은 기능이 필요해집니다. 그런데 I/O 디바이스가 페이지 폴트를 일으키는 방법은 기존의 구조에서 고려하지 않았습니다. 그래서 기존의 I/O 디바이스용 MMU(Memory Management Unit. 메모리 관리 유닛)를 확장하고 I/O 디바이스의 페이지 폴트를 받는 확장이 필요해지게 됩니다. 이것이 IOMMU v2라고 불리는 것입니다.

 

29.jpg

 

다음은 캐시 일관성입니다. 기존의 멀티코어 CPU에선 CPU 코어에 딸린 캐시(L1/L2 캐시)에 대해서 캐시 일관성을 유지하고 있었습니다. 이 그림은 캐시 일관성을 설명한 것인데 4코어 CPU는 1코어마다 공유 L2 캐시를 가지고 있습니다.

 

여기서 CPU#1에 할당된 메모리 영역에 데이터를 기록한다고 칩시다. 그 경우 우선 L1 캐시에 저장되며 L2 캐시를 거쳐서 메모리에 기록됩니다(5-1). 이 때 만약 CPU#2~#4이 같은 메모리 영역을 캐시한다면 실제 메모리의 값과 캐시된 값이 엇갈리게 됩니다. 그래서 이 경우 각각의 캐시가 값은 값이 되도록 바꿔주야 합니다(5-2). 이로서 모든 캐시의 내용이 차이점이 없도록 하는, 다시 말해 캐시 일관성을 유지하는 매커니즘이 캐시 일관성입니다. 여기까지는 이야기가 단순하지만 여기에 GPU까지 끼어들면 CPU와 GPU 사이에 캐시 일관성도 취해야 합니다.

 

CPU와 GPU 사이에 캐시 일관성도 취하는 구조가 필요하다고 말은 간단하게 했지만, 이를 실현하기 위해선 AMD도 3세대에 걸쳐 도입을 하게 됩니다. 라노-트리니티-카베리로 가면서 어떻게 진화했는지를 간단하게 요약하면 이렇습니다.

 

라노: 어니언/갈릭의 2가지 내부 버스를 마련해 GPU 코어가 메모리를 광대역 접속하며, GPU→ CPU로의 캐시 일관성만 유지하는 구조

트리니티: 기본 구성은 라노와 같으나 IOMMU v2를 구현해 GPU 페이지 폴트를 하드웨어 레벨에서 지원, 어니언의 버스 폭을 두배로

카베리: 어니언+라는 버스가 추가되어 CPU→ GPU로의 일관성을 실현하기 위한 구조가 구현됨

 

카베리도 아직은 어정쩡합니다. 위 그림의 5-1에서 메모리 영역이 바뀌었을 경우, 5-2에서 해당 데이터를 캐시하고 있는 경우 데이터를 재기록(스누핑)해야 하는데, 이 스누핑은 일반적으로 그 어드레스를 캐시하고 있는지를 확인해야 합니다. 왜냐면 기존 영역을 고칠 때마다 무조건 다른 코어의 캐시에 새로고침 리퀘스트를 냈다면 트래픽의 양이 방대해지고, 캐시하지 않았다면 스누핑이 헛것이 되기 때문입니다.

 

그런데 카베리도 CPU에서 GPU 캐시 영역을 확인할 수 없으니 방대한 트래픽이 발생하게 됩니다. 이를 피하기 위해 카베리에선 어니언+를 경유할 경우 GPU의 L2 캐시를 우회하도록 구현했습니다. 이 구성은 카베리에 들어갔으나 아직 헤테로지니어스 구성에서 쓰기엔 완벽하지 않으며 이를 해결하기 위해선 시간이 더 필요할 것입니다. 다만 불충분하다 해도 일단 HSA 기반이 정돈되면서 CPU와 GPU가 분배를 하는 시스템이 정비된 것입니다. 여기에 추가로 hUMA나 hQ도 카베리에 들어가, 오픈CL 기반의 태스크에선 CPU와 GPU가 동등한 수준에 오르게 됐습니다.

 

현재 AMD의 문제는 하드웨어가 아니라 오히려 소프트웨어입니다. 먼저 GPU의 페이지 폴트가 하드웨어 레벨에서 지원됐다고 한 건, 아직 소프트웨어 쪽의 대응이 아직 갖춰지지 않았기 때문입니다. 사실 이것은 OS의 문제로 현재의 윈도우에선 HSA를 최대한 활용할 수 없습니다. AMD 혼자서는 어떻게 해결할 수 없는 문제며 여러 OS 개발사와 협의중이긴 하나 구체적인 스케줄은 아직 확실하지 않습니다.

 

이러한 움직임과 대조적인 게 NVIDIA입니다. CUDA가 GPU를 가속하는 API로 널리 보급되면서 여기서 벗어나기 어려워진 면도 있지만, NVIDIA가 이렇게 한 가장 큰 문제는 CPU가 없고 GPU만 있다는 것입니다. 물론 2010년에 PC용 칩셋에서 철수를 밝히기 전부터, ARM 기반의 SoC로 제품 전개를 바꿔 지금까지 이르렀지만요.

 

다만 현재의 테그라 시리즈는 모바일용 제품으로 절대적인 성능은 낮습니다. 최소한 NVIDIA 자신의 테슬라를 구동할만한 CPU 성능과 I/O 성능을 갖추고 잊지 못합니다. 따라서 모바일은 고사하고 HPC를 비롯한 CUDA의 주요 전장에선 계속해서 인텔 플랫폼을 쓸 수밖에 없습니다. 그 경우 PCI-E 기반 가속 카드 이상으로 진화하기란 물리적으로 어렵습니다(고성능 ARM을 개발하고 있긴 하지만). 그래서 가속 프로세서로서 성능을 높이면서 CUDA를 다른 환경에 대응할 수 있도록 조금씩 바꿔가고 있는데 그 징후는 현재도 조금씩 보이고 있습니다.

 

PC의 메모리와 일관성을 유지해 고속 전송하는 것이 당분간 불가능하다면, 그래픽카드에 대량의 고속 메모리를 넣어 성능을 개선하는 방법밖에 없으며, 이를 위한 것이 TSV(Through Silicon Via)를 사용한 3D 스택 DRAM이나 OpenACC의 추가입니다. 이 중 TSV를 이용한 3D 메모리는 코드네임 볼타로 구현된다고 2013년의 GTC에서 공개됐으며, 볼타와 같은 시기에 나올 테그라인 파스칼 역시 3D 스택 DRAM을 쓴다고 밝혀졌습니다.

 

또 CPU와의 협력의 경우 맥스웰이 CPU 코어를 통합해 나가는 방향이며, 2015년에 출시될 것으로 예상되는 맥스웰의 하이엔드 GPU는 자사의 ARM v8 코어인 덴버가 탑재될 것입니다. 물론 이것도 AMD처럼 캐시 일관성 구조를 도입해 나갈 필요가 있지만, CUDA 자체가 아직 HSA만큼 CPU/GPU의 협업을 전제로 하지 않으니 그 정도로 복잡한 구조는 아직까진 필요하지 않습니다. 이에 앞서 2013년 5월에 발표된 CUDA 5.5에선 ARM에 대한 대응이 구현되어 있습니다. 현실적으로 CUDA를 이용하기 위해선 G80 이후의 코어가 필요하며 G70 기반의 테그라 4까진 의미가 없습니다. 테그라 계열에선 테그라 K1이 첫 CUDA 기반 제품으로 맥스웰이 덴버를 구현하는 것도 이에 준하는 형태가 될 것이지 싶습니다.

 

그리고 더욱 고급형으로 NVIDIA가 발표한 것이 NVLink입니다. GPU-CPU와 GPU-GPU의 인터커넥트로서 IBM 파워 프로세서가 NV링크를 지원한다는 것도 알려졌습니다. 자세한 스펙은 알려지지 않았지만(물리층은 물론 프로토콜까지도) 적어도 PCI-E의 연장선상에 있는 건 아닌 걸로 보입니다. NV링크로 연결된 디바이스는 기존 확장 카드와 다른 I/O 디바이스로 취급될 가능성이 있습니다. PCI-E에선 불가능했던 캐시 스누핑도 구현될 가능성이 있으며 신호 자체도 매우 빨라 80~200GB/s의 대역이 가능합니다. 3D 스택 DRAM에 비하면 느리지만(이건 1TB/s) PCI-E에 비하면 매우 빠릅니다. PCI-E와 같이 써도 효율을 대폭 높일 수 있을 것이라 기대할 만 합니다.

 

AMD와 NVIDIA가 GPGPU의 성능을 높이는 근본적인 방법은 같지만, 해결책에서 큰 차이를 보이는 부분이 있습니다. 바로 CPU를 갖고 있느냐는 것인데 이것이 그대로 솔루션의 차이로 드러나고 있습니다. 최근 AMD는 HPC 시장을 버렸다는 말이 HPC 업계에서 자주 나오고 있으나, AMD의 솔루션은 외장형 그래픽을 포기한 것에 가깝습니다. 반대로 NVIDIA의 솔루션은 HPC에 특화하는 방향으로 나아가고 있지만, 그 시장을 제대로 장악할 수 있는지가 문제가 되겠지요. 

 

소스:

http://pc.watch.impress.co.jp/docs/column/1month-kouza/20140404_642769.html

http://pc.watch.impress.co.jp/docs/column/1month-kouza/20140411_643848.html

http://pc.watch.impress.co.jp/docs/column/1month-kouza/20140418_644945.html

http://pc.watch.impress.co.jp/docs/column/1month-kouza/20140425_646073.html

기글하드웨어(http://gigglehd.com/zbxe)에 올라온 모든 뉴스와 정보 글은 다른 곳으로 퍼가실 때 작성자의 허락을 받아야 합니다. 번역한 뉴스와 정보 글을 작성자 동의 없이 무단 전재와 무단 수정하는 행위를 금지합니다.