연산자 성능 최적화

연산자 성능 최적화 (Operator Performance Optimization)

Ascend NPU에서 Triton 연산자의 성능 데이터를 수집하고 병목을 분석·최적화하는 방법을 다룹니다.

출처: 문서

본문

Performance_benchmark

성능 데이터 획득 (Obtaining Performance Data)

성능을 최적화하기 전에 정확한 성능 데이터를 얻고, 현재 성능 상태를 이해하며, 성능 상태에 기반한 다음 최적화 방향을 분석해야 합니다. MindStudio는 Triton 연산자의 성능을 테스트하는 현실적인 방법을 제공합니다.

디바이스 측 (Device-end)

msProf 도구는 Ascend AI Processor에서 실행되는 연산자의 핵심 성능 지표를 수집·분석하는 데 사용됩니다. 출력 성능 데이터로 연산자의 소프트웨어·하드웨어 성능 병목을 빠르게 찾고 연산자 성능 분석 효율을 높일 수 있습니다.

msprof op python3 test_xxxxx.py

다음은 msprof로 데이터 수집을 수행한 사례입니다.

속성 (Attribute) 값 (Value)
Name DequantSwigluQuant_int32_high_performance_100000000
Type DequantSwigluQuant
OP State static
Accelerator Core AI_VECTOR_CORE
Start Time(us) 1774489226717521.715
Duration(us) 102.824
Wait Time(us) 0
Block Dim 36
Mix Block Dim 0
HF32 Eligible NO
Input Shapes 163840,1024;128,1024;163840;;;;128
Input Data Types INT32;FLOAT;FLOAT;DT_UNDEFINED;DT_UNDEFINED;DT_UNDEFINED;INT64
Input Formats ND;ND;ND;NULL;NULL;NULL;ND
Output Shapes 163840,512;163840
Output Data Types INT8;FLOAT
Output Formats ND;ND
Context ID N/A
aicore_time(us) 0
aic_total_cycles 0
aic_mac_time(us) 0
aic_mac_ratio 0
aic_scalar_time(us) 0
aic_scalar_ratio 0
aic_mte1_time(us) 0
aic_mte1_ratio 0
aic_mte2_time(us) 0
aic_mte2_ratio 0
aic_fixpipe_time(us) 0
aic_fixpipe_ratio 0
aic_icache_miss_rate 0
aiv_time(us) 59.128
aiv_total_cycles 3512188
aiv_vec_time(us) 36.708
aiv_vec_ratio 0.621
aiv_scalar_time(us) 41.403
aiv_scalar_ratio 0.7
aiv_mte2_time(us) 11.975
aiv_mte2_ratio 0.203
aiv_mte3_time(us) 9.738
aiv_mte3_ratio 0.165
aiv_icache_miss_rate 0.005
cube_utilization(%) 0

아래는 공식 사양에 맞춘 연산자 성능 레코드의 필드별 분석입니다.

1. 기본 식별 필드 (Basic Identification Fields)

필드 (Field) 값 (Value) 정의 (Definition per official docs)
Name DequantSwigluQuant_int32_high_performance_100000000 Op Name: 융합 연산자(디양자화 + SwiGLU 활성화 + 양자화)의 이름, int32 고성능 구현 접미사 포함.
Type DequantSwigluQuant OP Type: 연산자의 기능 범주.
OP State static OP State: 형태와 스케줄링 로직이 컴파일 시 결정되는 정적 연산자.
Accelerator Core AI_VECTOR_CORE Task Type: 연산자가 AI Vector Core에서 실행됨. 다른 일반 유형은 AI_CORE(행렬 연산 코어)와 AI_CPU.

2. 타이밍·스케줄링 필드 (Timing & Scheduling Fields)

필드 (Field) 값 (Value) 정의 (Definition per official docs)
Start Time(us) 1774489226717521.715 Task Start Time: 디바이스 측 연산자 작업의 절대 시작 타임스탬프(마이크로초).
Duration(us) 102.824 Task Duration: 디스패치 시간, 가속기 실행 시간, 완료 응답 시간을 포함한 연산자의 종단 간 총 지연(마이크로초).
Wait Time(us) 0 Task Wait Time: 이전 작업 종료와 현재 작업 시작 사이의 시간 간격. 0은 작업 디스패치 사이에 유휴 대기 없음을 의미.

3. 핵심 구성·정밀도 필드 (Core Configuration & Precision Fields)

필드 (Field) 값 (Value) 정의 (Definition per official docs)
Block Dim 36 Block Num: 연산자 작업의 병렬 스레드 블록 수. SIMT 프로그래밍 모델의 Block Dim에 해당. 하나의 AI Vector Core는 한 번에 하나의 스레드 블록만 실행하므로 이 값은 점유된 병렬 연산 리소스 규모를 반영.
Mix Block Dim 0 Mix Block Num: 연산자가 AI Core와 Vector Core 모두에서 실행되면 보조 가속기의 블록 수. 0은 연산자가 하이브리드 코어 스케줄링 없이 AI_VECTOR_CORE 전용으로 실행됨을 의미.
HF32 Eligible NO HF32 Eligible: HF32 고정밀 부동소수점 형식 활성화 여부. NO는 사용되지 않음을 의미. 이 필드는 --task-time=l1 수집 수준에서만 보고.

4. 입력·출력 정보 (Input & Output Information)

필드 (Field) 값 (Value) 정의 (Definition per official docs)
Input Shapes 163840,1024;128,1024;163840;;;;128 Input Shapes: 각 입력 텐서의 차원(세미콜론으로 구분). 빈 값은 스칼라 입력. 7개 입력: 형태 [163840,1024], [128,1024], [163840], 스칼라 3개, [128].
Input Data Types INT32;FLOAT;FLOAT;DT_UNDEFINED;DT_UNDEFINED;DT_UNDEFINED;INT64 Input Data Types: 입력 데이터 타입. 입력 형태와 같은 순서.
Input Formats ND;ND;ND;NULL;NULL;NULL;ND Input Formats: 입력 메모리 레이아웃. ND는 N차원 텐서 형식, NULL은 스칼라/정의되지 않은 입력.
Output Shapes 163840,512;163840 Output Shapes: 두 출력 텐서의 차원(세미콜론 구분): [163840,512][163840].
Output Data Types INT8;FLOAT Output Data Types: 출력 1은 INT8(양자화 결과), 출력 2는 FLOAT.
Output Formats ND;ND Output Formats: 두 출력 모두 표준 ND 레이아웃.
Context ID N/A Context ID: Sub Task 세분화의 하위 작업 식별자. N/A는 이 연산자에 하위 작업 분할이 없음을 의미.

5. AI Core 성능 메트릭 (aic_* 시리즈)

필드 (Field) 값 (Value) 정의 (Definition per official docs)
aicore_time(us) 0 AI Core에서의 이론적 실행 시간(마이크로초).
aic_total_cycles 0 AI Core에서의 총 실행 사이클.
aic_mac_time(us) / aic_mac_ratio 0 / 0 cube(행렬 곱) 명령의 지연과 사이클 비율.
aic_scalar_time(us) / aic_scalar_ratio 0 / 0 스칼라 명령의 지연과 사이클 비율.
aic_mte1_time(us) / aic_mte1_ratio 0 / 0 L1→L0A/L0B 데이터 이동 명령의 지연과 사이클 비율.
aic_mte2_time(us) / aic_mte2_ratio 0 / 0 DDR→AICORE 읽기 이동 명령의 지연과 사이클 비율.
aic_fixpipe_time(us) / aic_fixpipe_ratio 0 / 0 L0C→OUT/L1 이동 명령의 지연과 사이클 비율.
aic_icache_miss_rate 0 AI Core의 명령 캐시 미스율.

6. AI Vector Core 성능 메트릭 (aiv_* 시리즈)

필드 (Field) 값 (Value) 정의·해석 (Definition & Interpretation)
aiv_time(us) 59.128 aiv_time: 모든 블록이 동일 지속 시간으로 동시 스케줄링되는 이상 조건에서 Vector Core의 이론적 실행 시간. 실제로는 블록 시작이 엇갈려 이 값이 실제 실행 시간보다 약간 작음.
aiv_total_cycles 3512188 aiv_total_cycles: 모든 블록에 걸쳐 합산된 Vector Core 총 실행 사이클.
aiv_vec_time(us) / aiv_vec_ratio 36.708 / 0.621 벡터 연산 명령의 지연(us)과 사이클 비율(62.1%). 벡터 연산이 이 연산자의 핵심 연산 워크로드.
aiv_scalar_time(us) / aiv_scalar_ratio 41.403 / 0.7 스칼라 명령의 지연(us)과 사이클 비율(70%). 스칼라와 벡터 파이프라인은 독립 카운터로 병렬 실행되므로 합이 100%를 초과.
aiv_mte2_time(us) / aiv_mte2_ratio 11.975 / 0.203 읽기 메모리 이동 명령(DDR/온칩 메모리 → Vector Core)의 지연과 사이클 비율(20.3%).
aiv_mte3_time(us) / aiv_mte3_ratio 9.738 / 0.165 쓰기 메모리 이동 명령(Vector Core → DDR/온칩 메모리)의 지연과 사이클 비율(16.5%).
aiv_icache_miss_rate 0.005 Vector Core 명령 캐시 미스율 0.5%. 극히 낮으며 효율적 명령 페치를 나타냄.

7. 활용도 메트릭 (Utilization Metrics)

필드 (Field) 값 (Value) 정의 (Definition per official docs)
cube_utilization(%) 0 cube_utilization: 행렬 곱 단위의 활용률. 연산자가 순수 벡터 기반이므로 값이 0.

최적화 (Optimization)

사양 (Specification)

1. Ascend 코어 연산 유닛

  • AI Core: 실제로 행렬/벡터 연산을 수행하는 코어
  • Vector Unit: SIMD 연산 담당(CUDA Core와 유사)
  • Scalar Unit: 제어/루프 담당
  • L0/L1/L2 캐시: 크기가 작을수록 빠름. L0는 64KB, L1은 256KB, L2는 공유.

2. Ascend 메모리 계층 (빠른 것부터 느린 것)

  • 레지스터 (Register) → 가장 빠름
  • L0/L1 캐시 → 매우 빠름
  • 온칩 캐시 (L2) → 빠름
  • DDR (호스트 메모리) → 가장 느림

3. Ascend 명령의 특성

큰 연속 메모리 블록 접근에 강함

이산 접근, 스트라이드 접근, 랜덤 접근을 싫어함

128비트/256비트 정렬이어야 함

벡터화되어야 함

팁 (Tips)

  1. A2/A3 시리즈 제품은 보통 벡터 코어가 40개 또는 48개뿐입니다. grid 수가 40/48 벡터 코어를 초과하면 grid가 큐에 전달되어 대기 시간이 길어집니다. 따라서 고성능 구현의 코어 수는 벡터 코어 수를 초과하지 않아야 합니다.
  2. 사용 가능한 UB를 최대한 모두 사용하세요. 한 번에 큰 블록 크기를 옮겨 바운드가 MTE에 있도록 하세요. 중복 복사(Redundant Copy) 금지.
  3. 오프셋이 음수이면 현재 triton-ascend는 이를 이산 메모리 접근 시나리오로 간주합니다. 결과적으로 성능이 크게 저하되며 데이터가 스칼라 모드로 읽히는 대신 전체 DMA 블록에서 읽힙니다.
  4. Ascend 하드웨어의 UB는 텐서의 꼬리 축(tail axis) 크기가 32바이트로 정확히 나누어질 것을 요구합니다. 꼬리 축 길이가 부족하면 자동으로 보충됩니다. 예를 들어 형태 (2048, 3) 텐서는 자동 보충으로 성능이 지수적으로 저하됩니다. 이 경우 transpose로 정렬 축을 더 낮은 차원으로 바꿀 수 있습니다. 또한 transpose 연산도 자동 보충 규칙의 영향을 받으므로 보충을 피하는 특별한 기술도 필요합니다.
  5. Double Buffer를 사용해 연산과 데이터 전송을 병렬화하세요. 한 데이터 블록을 연산하는 동안 다른 블록을 L1로 전송합니다.
  6. hostbound 동작이 심하면 코어 바인딩(core binding)으로 해결할 수 있습니다.

더 알아보기 (Learn more)