[GPU] Mali Valhall Architecture (Mobile GPU)

Previous GPU Architecture (Bifrost GPU)

지난 5월(2019년)에 Mali의 새로운 GPU Architecture Valhall이 공개되었다. 지난 Bifrost 대비 많은 변화가 있었다고 한다. 우선 지난 Bifrost에 대해서 짧게 정리하였다. Bifrost는 지난 2016년에 처음 공개되어서 그림 1과 같이 Mali-G71, Mali-G72, Mali-G76 순서대로 총 3세대(High-Tier GPU 기준)에 걸쳐서 제품으로 출시되었다. Bifrost는 ARM GPU 중 최초로 Scalar GPU 구조로 되어 있다. Bifrost 이전 GPU Architecture는 Vector 연산 구조를 사용하였다. Scalar GPU 구조는 Desktop GPU를 만드는 NVIDIA, AMD에서 사용하는 GPU 연산 구조이다.

그림 1: Midgard, Biforst, Valhall GPU 구조 변경 사항 (출처 1)

HISilicon의 Kirin, Samsung의 Exynos는 Bifrost GPU 구조를 사용한 SoC Chip을 생산하였다. 그리고 해당 제품의 GPU 성능은 타사 제품 (Apple, Qualcomm) 대비 성능, 파워 측면에서 실망스러운 제품이라고 한다. 덕분에 Qualcomm은 한발 앞서나가게 되었고, Apple이 A12를 발표함으로 ARM GPU와의 성능 차이가 더 큰 폭으로 벌어져 버렸다.


Introducing Valhall GPU

Mali-G77은 새롭게 공개된 Valhall GPU 구조를 가진 제품이다. Valhall GPU는 새로운 ISA(Instruction Set Architecture)를 사용한다고 한다. 새로운 ISA 구조는 기존 Desktop GPU를 만드는 NVIDIA, AMD와 비슷한 구조로 되어 있다. 위 그림1은 Midgard, Bifrost, Valhall에서 변경되거나 추가된 부분을 간단히 정리하여서 보여준다. 그림 2는 Valhall Architecture를 설계하면서 지향했던 목표와 변경 사항을 간단히 정리한 그림이다.

그림 2: Valhall Architecture Goals (출처 1)

Warp/Wavefront Size

보통 GPU는 SIMT(Single Instruction Multiple Thread) 또는 SIMD(Single Instruction Multiple Data) 구조로 만들어져있다. 하나의 Instruction을 사용해서 여러 개의 Thread(Data)의 연산을 동시에 수행하는 구조이다. 기존 Bifrost의 경우 4 또는 8개의 Thread의 연산을 동시에 수행하는 구조였다. Valhall의 경우 16개의 Thread가 하나의 Instruction 연산을 수행하는 구조로 변경되었다. 16개는 Desktop GPU를 만드는 NVIDIA(32개-Warp), AMD(64개-Wavefront)에 비하면 아직도 작은 편이다.

한 번에 실행하는 Thread 개수(Warp/Wavefront 사이즈)에 따른 장/단점이 존재한다. 편의를 위해서 한 번에 Lock-Step으로 실행되는 Thread의 묶음을 Warp라고 표현할 예정이다. Warp 사이즈를 크게 하면 Control Logic의 Overhead가 줄어서 장점이 생긴다. 반면 Divergence, 충분하지 못한 Thread(Data) 개수 등으로 인해서 Idle Cycle 수가 증가하는 단점이 발생한다.

출처 1의 내용에 따르면 이전 ARM GPU가 Warp 사이즈를 4, 8개로 작게 가져간 이유는 2016년 당시만 해도 GPU에 충분한 양의 Workload가 없어서 많은 Thread 연산을 한 번에 수행할 필요가 없었기 때문이다. Thread를 많이 생성하지 못하는 Workload에서 큰 Warp 사이즈를 사용하면 Idle Cycle의 증가로 효율성이 하락하는 문제가 발생한다. 하지만, 2019년에는 PC에서 제작된 게임들이 Mobile로 넘어오면서 Workload가 급격히 증가하였다. 다시 말해서 Workload가 많아지면서 Warp 크기를 증가시켜서 얻을 수 있는 이득이 더 많아졌다는 의미이다. 아래 그림 3은 Warp 사이즈를 늘려서 Instruction을 수행하는 예제를 보여준다.

그림 3: Warp/Wavefront 사이즈 변경 (출처 1)

Valhall Engine Microarchitecture

그림 4: Valhall Engine (출처 1)

그림 4는 Mali-G77의 Engine Microarchitecture 구조 그림이다. 기존 Mali GPU (Bifrost, Midgard)의 경우 Execution Engine마다 Instruction Scheduler, Instruction Cache, Register를 따로 내장하고 있었다고 한다. 결과적으로 Control Logic에 따른 Overhead가 높은 편이었다. Valhall은 Scheduler, Instruction Cache 등 공유 가능한 Control Logic을 하나로 합쳐서 Processing Unit (Execution Unit)이 공유하는 형태이다. 그림 5는 Valhall의 Front-End (Control Logic 관련) 구조 그림이다. Valhall의 경우 총 64개의 Warp (1024 Thread)를 동시에 수행할 수 있다. Front-end에서 Warp의 Stat을 관리하고 Scheduling을 담당한다.

그림 5: Valahll Front-End 구조 (출처 1)

Valhall은 Scheduling 방식에 큰 변화가 있다. 기존 Mali GPU는 Clauses/Tuples라는 Fixed Issue Scheduling 방식을 사용했다고 한다. Fixed Issue Scheduling 방식을 대략적으로 설명하면 Compiler가 Scheduling의 Dependency를 계산하여서 Instruction Group을 생성한다. Group 안의 Instruction은 Dependency가 존재하지 않고, Group 간에는 Instruction Dependency가 존재한다. 하나의 Group에 속해 있는 Instruction을 Scheduling 할 경우 Dependency가 없는 관계로 그냥 Scheduling 하면 된다. 하지만, Group이 변경되면 해당 Dependency가 해결될 때 까지 Pipeline Stall이 발생한다. 이러한 방법은 이론상(?)은 좋은 성능을 보이지만 Compiler 과정에서 Overhead가 많이 발생하고 실제로는 Scheduling이 잘되지 않는다고 한다.

MK: 위 설명이 정확한지 잘 모르겠다. 대략 이해한 부분을 정리하였다. 추가로 Clauses/Tuples는 약간 VLIW (Very Long Instruction Word)와 같은 느낌이 든다. 상세한 내용은 다르지만, 병렬성을 높이기 위한 기법인 것 같다.

Valhall GPU는 Compiler의 도움 없이 모든 Scheduling을 하드웨어에서 수행한다. CPU의 Out-Of-Order(OOO) 또는 In-Order와 비슷한 구조라고 생각하면 될 것 같다. 추가로 I-Cache의 크기는 16KB로 총 2,048개의 Instruction을 저장할 수 있으며 4-Way Set Associative 구조를 가진다. 총 4개의 Instruction이 한 번에 Scheduling 가능하다고 한다.

그림 6: Valhall Processing Unit 구조 (출처 1)

그림 6은 Valhall의 Engine Processing Unit 구조 그림이다. 각 Processing Unit은 3개의 다른 ALU 연산기(FMA, CVT(convert), SFU(Speical Function Unit))로 구성되어 있다. FMA, CVT는 16-Wide로 16개의 Thread 연산을 한 번에 수행할 수 있다. 반면 SFU는 4-Wide로 1개의 Warp(16 Thread) 연산을 수행하기 위해서 4번의 연산이 필요하다. 추가로 FMA의 경우 1 Cycle에 16개의 32-Bit 연산을 수행할 수 있으며, 16-Bit 연산의 경우 32개, 8-Bit 연산의 경우 32개의 2배인 64개 연산을 수행할 수 있다. 

각 Processing Unit은 4개의 Fetch Unit을 가지고 있으며, Register와 Tightly Coupled 되어 있다고 한다. 개인적인 추측인데 아마도 Front-end에서 보낸 Register 값과 Instruction을 Processing Unit에 저장했다가 연산을 수행하는 것으로 판단된다.

그림 7: Mali-G76 vs. Mali-G77 연산 Latency (출처 1)

그림 7은 Mali-G76(Bifrost)과 Mali-G77(Valhall)의 Processing Unit 연산 순서를 보여준다 (연산 Latency가 정확한 표현인 것 같다). Valhall의 경우 기존 Bifrost 대비 연산 Depth(Datapath) 길이가 짧다. 기존 Bifrost의 경우 하나의 Instruction 연산을 수행하는데 8 Cycle의 시간이 필요하다. 반면, Valhall의 경우 4 Cycle의 연산 Latency를 가진다고 한다. 정리하자면 Valhall은 SuperScalar와 비슷한 구조로 되어 있으며 연산이 다른 경우 여러 개의 ALU를 사용해서 Instruction을 수행할 수 있다. 결과적으로 Compiler가 연산 가능한 Instruction을 찾지 않고 하드웨어 Scheduler가 Scheduling 가능한 Instruction을 찾기 때문에 Compiler Friendly 한 ISA라고 표현하는 것 같다.


Texture Mapping Unit (TMU) & Load/Store Units (LSU)

그림 8: Mali-G77 Shader Core 구조 (출처 1)

그림 8은 Mali-G77 Shader Core 구조 그림이다. 그림의 초록색 부분은 앞에 설명한 Engine Processing Unit 부분이다. 전체적으로 지난 세대와 큰 차이가 없다. 큰 변화가 있는 부분은 TMU이다. 이전 세대 대비 Throughput이 2배 증가하였다. 그림에 노랑색으로 표시되어 있다.

그림 9: Texture Mapping Unit (TMU) 구조 (출처 1)

그림 9는 TMU 구조 그림이다. 큰 그림으로 보면 지난 세대와 이번 세대의 구조가 크게 다르지 않다. TMU는 크게 2가지 Path로 나뉜다. 하나는 Hit-Path, 다른 하나는 Miss-Path이다 (너무 당연한 거 아닌가??). Hit-Path의 경우 Miss-Path 대비 Data Loading Latency가 짧다. Texture Cache 사이즈는 32KB로 증가하였고 한 사이클 당 16-Texel을 Loading 할 수 있다. 이는 전작인 Mali-G76 대비 Throughput이 2배 증가한 수치이다. 놀라운 사실이라고 하면 Throughput을 2배 증가시켰지만 다이 크기는 지난 세대와 큰 차이가 없다고 한다. 그림 10은 Mali-G72, Mali-G76, Mali-G77 GPU의 TMU Throughput을 비교한 그림이다.

그림 10: TMU Throughput 비교 (출처 1)

다음은 Load-Store Unit (LSU) 이다. 아래 그림 11은 LSU 구조이다. 역시나 기본적으로 전 세대와 비슷한 구조로 되어 있다고 한다. 달라진 점은 Pipeline Stage 수를 줄여서 Latency를 줄였고, Full-Cache Line을 Loading 할 수 있도록 변경하였다고 한다. 이전 세대 GPU의 LSU는 Full-Cache Line을 로딩하지 않고 Half-Size(절반) 사이즈를 로딩하였다. Throughput이 증가하면 ML(Machine Learning) Workload 성능이 크게 향상된다고 한다.

그림 11: Load Store Unit (LSU) 구조 (출처 1)

 Putting All Together

그림 12: Valhall GPU Design (출처 1)

더 큰 그림으로 보면 Mali-GPU는 여러 개의 Shader로 구성되어 있다 (그림 12 참조). GPU는 최소 1개에서 최대 32개의 Shader Core를 가질 수 있도록 설계하였으나 현시점(2019년 5월)에는 16개만 지원한다고 한다. L2 Cache 총 4개의 Slice로 구성되어 있으며 각 Slice는 최소 256KB(전체 1MB)에서 최대 1MB(전체 4MB)까지 변경할 수 있다. 대부분의 Vendor가 2MB (각 Slice 당 512KB) 사이즈로 구성한다. 위에서 언급한 바와 같이 L2에서 LSC(Load-Store Cache) Loading 사이즈가 기존 32B/Cycle에서 64B/cycle로 2배 늘어났다. L2에서 외부 Memory와의 Memory Loading Bandwidth는 각 Vendor가 128-Bit, 256-Bit 중 선택 가능하다.


Performance

그림 13: Mali-G77 성능 향상 그래프 (출처 1)

Valhall은 이전 세대 GPU 대비 몇 가지 변화가 있었다. 그림 13은 Valhall GPU의 성능 향상 결과 그래프이다. ARM은 보통 성능을 측정할 때 Performance/mm2를 사용한다고 한다. 기존 Mali-G76 GPU 대비 대략 1.2x ~ 1.4x Performance/mm2 향상이 있다고 한다. 보통 스마트폰 파워 Budget(TDP)이 대략 4~5W로 알려져 있다. 그래서 성능 향상도 중요하지만 Power Efficiency 향상 폭도 중요한 부분이다. 그림 14는 지난 세대 GPU 대비 Energy Efficiency 향상 그래프 결과이다. Mali-G77은 이전 세대 GPU 대비 1.2x ~ 1.39x Performance/W 성능 향상이 있다고 한다. 

그림 14: Power Efficiency 향상 결과 그래프 (출처 1)
그림 15: ML Workload 성능 향상 그래프 (출처 1)

그림 15는 ML Workload를 실행하였을 때의 성능 향상 그래프이다. Mali-G77은 기존 GPU 대비 대략 33%의 성능 향상을 가져온다고 한다. 

현재까지 주어진 결과를 기준으로 Mali-G76 GPU를 가진 Exynos 9820의 Mali-G76 GPU를 Mali-G77로 변경하면 다음 세대 Exynos GPU는 엄청난 성능 향상이 기대할 수 있다고 한다. 하지만 올해 한국에 출시되는 Samsung Galaxy S20은 Qualcomm Chipset을 사용한다 (출처 2). 이론상 큰 성능 향상이 있음에도 불구하고 오히려 Qualcomm Chipset을 선택한 이유가 궁금하다. 


출처

  1. https://www.anandtech.com/show/14385/arm-announces-malig77-gpu
  2. https://namu.wiki/w/%EA%B0%A4%EB%9F%AD%EC%8B%9C%20S20
  3. https://community.arm.com/developer/tools-software/graphics/b/blog/posts/introducing-arm-mali-g77-with-new-valhall-architecture?_ga=2.64241703.9689817.1581498219-1772889150.1529367585
  4. https://www.anandtech.com/show/10375/arm-unveils-bifrost-and-mali-g71/2

Leave a Comment