본문 바로가기
학부생의학부연구생/_paper

[MobiSys 2022] mGEMM: Low-latency Convolution with Minimal Memory Overhead Optimized for Mobile Devices (4)

by 호상 🐧 2022. 8. 18.

# 세미나를 위한 논문 summary

# 2022  MobiSys에서 발표된 논문

# 오역이 있을 수 있습니다.

# 2022 08 30 seminar

 

# ACM reference Format : JongseokPark,KyungminBin,andKyunghanLee.2022.mGEMM:LowlatencyConvolutionwithMinimalMemoryOverheadOptimizedforMobile Devices.InThe20thAnnualInternationalConferenceonMobileSystems, ApplicationsandServices(MobiSys’22),June25–July1,2022,Portland,

https://dl.acm.org/doi/10.1145/3498361.3538940

 

mGEMM | Proceedings of the 20th Annual International Conference on Mobile Systems, Applications and Services

ABSTRACT The convolution layer is the key building block in many neural network designs. Most high-performance implementations of the convolution operation rely on GEMM (General Matrix Multiplication) to achieve high computational throughput with a large w

dl.acm.org

 

https://strangecat.tistory.com/71 ( 1 ) 

https://strangecat.tistory.com/74 ( 2 )

https://strangecat.tistory.com/75 ( 3 ) 

 

##

NEON SIMD 확장? :

 

ARMv8-A? :

 

FMA? :

 

(SVE)[42]? :

 

##

 

4 DETAILEDIMPLEMENTATIONS

 알고리즘의 진정한 고성능 구현을 만들려면 구현을 완료하기 위해 수행해야 하는 두 가지 작업이 있다. 1) 주어진 하드웨어에 최적의 매개 변수 값을 찾는 것2) 기본 하드웨어의 특징과 기능을 완전히 활용하는 코드를 만드는 것이다.

 

4.1 Understanding ARMv8-A and NEON

 우리는 구현을 위해 모바일 플랫폼의 사실상 표준인 ARMv8-A[2] 아키텍처에 중점을 두지만, 어떤 하드웨어로도 구현 할 수 있다. 본 알고리즘의 성능과 가장 관련이 있는 ARMv8의 주요 특징은 벡터 처리 기능, 즉 네온 SIMD 확장이다. NEON은 32개의 128비트 벡터 레지스터를 제공하며 8, 32, 64비트 모드에서 사용할 수 있다. NEON 벡터화된 부하 명령은 순차 메모리 공간에서 데이터를 로드해야 하기 때문에 데이터에 32비트 float 를 사용할 때 4개의 순차적 요소, 즉 128개의 요소를 가진 최대 32개의 벡터를 저장할 수 있다. 네온은 또한 MAC 작업의 최적화된 하드웨어 구현인 FMA를 제공한다. ARMv8-A의 계산 파이프라인을 완전히 포화시키려면 충분한 수의 독립적인 FMA 명령을 제공해야 한다. 필요한 명령어의 정확한 수는 미러 아키텍처에 따라 다르지만 일반적으로 8개 이상의 명령어로 충분하다고 간주된다. 즉, 출력 요소에 대해 최소 8개의 벡터 레지스터 또는 co×wo ≥ 32가 필요하다. 이것은 또한 로드와 스토어 명령어를 인터리브할 수 있는 충분한 FMA 명령어를 제공하여 메모리 동작과 계산을 병렬로 실행할 수 있게 하여 ARMv8-A 아키텍처의 명령 수준 병렬화(ILP) 기능을 활용한다.

 

4.2 Kernel Parameter Selection

 섹션 3에서 언급했듯이, 목표는 MAC(수식 1)당 메모리 동작을 최소화하는 blocking parameters c(i), c(o), w(o), w(f)의 조합을 찾는 것이다. 또한 아키텍처상의 한계도 있다.

수식 1

 

• Available registers: c(o)×w(o)+c(i)×w(o)+c(o)×w(f) ≤128 (2)

• Saturating the pipeline: c(o) ×w(o) ≥ 32 (3)

 Vectorized load granularity: c(o)와 c(i)는 메모리 상의 가장 안쪽 차원인 SIMD 벡터 레인 크기 4의 배수여야 한다.

(2) : 레지스터에 저장할 수 있는 최대 32비트 float 데이터 수
(3) : FMA 파이프라인을 포화시키는 데 필요한 최소 출력 요소 수

 

 섹션 3에서, 최적화를 통해 출력 레지스터 데이터 재사용을 위해 전체 C(in)을 활용하면서 c(i)를 1로 설정할 수 있었다. 불행히도, 네온의 벡터화된 부하 명령의 한계로 인해 c(i)는 4의 배수가 되어 입력 요소에 필요한 것보다 4배 많은 레지스터를 소비한다. 

 ARM의 차세대 벡터 확장 기능인 Scalable Vector Extension 기능(SVE)[42]은 이 문제를 완전히 해결하는 수집 유형 벡터 로드 명령을 제공한다. SVE를 사용하여 추가 레지스터 공간을 확보하면 커널에 H(fil) 차원을 포함시켜 W(fil) 차원만 추가된 현재 버전보다 훨씬 완전하고 효율적인 mGEMM 커널 버전을 만들 수 있을 것으로 믿는다. SVE는 현재 ARMv8-A에서 비표준 기능이지만 차세대 ARM 아키텍처인 ARMv9에서 널리 사용될 것으로 예상된다.

 매개 변수 공간을 검색한 결과, c(o) = 8, c(i) = 4, w(o) = 8, w(f) = 1 이 (수식2 ) 의 MAC 값당 메모리 연산 이 가장 좋은 결과를 달성하고 W(fil) = 3, C(in) = 256일 때 MAC당 약 0.140 load / stores 를 제공한다. 이것을 flops/byte로 변환하면 레지스터 수준에서 2 / (0.165×4) = 2.96을 얻을 수 있다.

이 값은 행렬 곱셈 커널이 달성할 수 있는 값보다 훨씬 높다. ARMv8에서 사용할 수 있는 MAC 값당 최소 메모리 액세스 권한을 가진 단일 소켓 GEMM 커널을 살펴보면, 차단 매개 변수는 m = 8, n = 12, k = 1이며, MAC당 메모리 액세스는 ( 2 / K + 1 / 8 + 1 / 12), K = 3 x 256 = 768일 때 대략 0.211이다. 이것을 바이트당 플롭으로 변환하면 레지스터 수준에서 2 / (0.211×4) = 2.37을 얻을 수 있다. 이는 mGEMM이 로드된 바이트당 약 25% 더 많은 계산을 처리한다는 것을 의미하며, 이는 실험 평가에서 관찰된 성능 향상 수준과 대략 일치한다.

 

4.3 Automated inner kernel generation

 지금까지 입력 텐서의 공간 차원을 출력 텐서의 공간 차원과 동일하게 편리하게 처리했다. 커널의 실제 구현에서 정확한 입력 요소의 공간 위치는 다양한 매개 변수의 복잡한 관계에 의해 결정되어야 한다. 

 다행히 위치를 결정하기 위한 연산은 복잡하지만 필요한 매개 변수가 설정되면 위치가 고정된다. 이 특성을 사용하여 올바른 입력 요소의 위치가 내부 커널에 내장될 수 있도록 각 내부 커널에 대해 w(f), c(o), w(o), stride, dilation 및 padding을 고정한다. 다양한 계층 구성에 대한 내부 커널을 쉽게 생성하기 위해 매개 변수 값을 취하고 FMA, 벡터화된 메모리 액세스 및 프리페치 명령과 같은 하드웨어 최적화와 함께 올바른 AArch64(ARMv8-A 64bit ISA) 어셈블리 내부 커널 코드를 출력하는 파이썬 스크립트를 작성한다. 우리는 원본 스크립트의 별도의 수정된 버전을 사용하는 깊이별 커널을 제외한 모든 내부 커널을 생성하기 위해 이 스크립트를 사용한다. 

 스크립트는 먼저 각 출력 공간 위치에 필요한 입력 공간 위치를 w(f), w(o), 패딩, 스트라이드 및 확장 매개 변수를 사용하여 계산한다. 스크립트는 중복되는 입력 공간 위치를 감지하고 각각의 고유한 입력 위치에 대해 하나의 128비트 벡터 레지스터를 매핑한다. 그런 다음 스크립트는 출력 값에 대해 적절한 수의 벡터 레지스터(일반적으로 w(o) × 2, c(o) = 8)를 매핑한다. 스크립트는 필터 액세스를 위해 나머지 벡터를 사용하며, 계산(FMA)과 메모리 액세스 명령의 적절한 인터리빙을 위해 적어도 두 개의 레지스터가 남아 있어야 한다. 만약 ARMv8 아키텍처가 제공하는 32개의 벡터 레지스터가 위의 할당을 만족시킬 수 없다면, 스크립트는 주어진 매개 변수가 하드웨어에 비해 너무 크다고 결론짓고 실패한다. 스크립트는 매개 변수 공간을 포함하는 중첩 루프 내에서 실행되어 지정된 하드웨어에 대한 최적의 매개 변수 조합을 찾을 수 있다. 

 충분한 레지스터가 있는 경우 스크립트는 먼저 하위 센서의 데이터를 보유하고 있는 레지스터에 대한 정보를 포함하는 레지스터 맵을 만든다. 그런 다음, ARMv8 어셈블리 명령어의 인쇄를 알고리즘 2의 8~13행으로 시작하고, 레지스터 맵에 의해 결정된 각 명령어의 참조 레지스터를 사용한다. 동일한 출력 데이터를 참조하는 FMA 명령은 가능한 멀리 배치되며, 레지스터의 데이터는 해당 데이터를 사용하는 모든 FMA 명령이 배치되는 즉시 새로운 로드 명령으로 대체된다. 새 로드 명령에 종속되지 않는 FMA 명령은 메모리 액세스 지연 시간을 숨기기 위해 뒤에 배치된다. L1 데이터 프리페치 명령은 FMA 명령 사이에 있고 메모리 액세스 명령에서 멀리 떨어져 있다. 가장 가까운 로드된 주소에서 +256의 주소 편향으로 데이터의 적시 액세스를 허용하고 계산 및 데이터 액세스 명령의 균일한 인터리빙을 허용한다.

이 스크립트를 사용하여 가장 최적의 매개 변수 조합으로 커널을 검색하고 생성했는데, 이는 섹션 4.2에서 설명한 값이다.우리는 또한 최적의 조합을 가진 커널이 필요한 계산 타일에 비해 너무 클 때 공백을 메우기 위해 4.2절보다 작은 매개 변수 크기의 커널을 생성했다.

 

알고리즘 2

댓글