1. 왜 PTX 와 SASS 를 봐야 하는가
CUDA kernel 을 작성할 때 우리가 보는 코드는 보통 C++ / CUDA 코드
x = x + c;
x = fmaf(x, a, b);
하지만 GPU 가 실행하는 것은 이 CUDA 코드가 아님,
실제 실행까지는 대략 다음 단계를 거침
CUDA C++ source
↓
NVCC front-end compilation
↓
PTX
↓
ptxas
↓
SASS
↓
GPU execution
중간 표현, PTX,
GPU architecture 에 맞는 SASS 로 변환
이를 통해 내가 의도한 instruction 구조가 GPU machine instruction 에도 유지되었는지 확인가능
compiler 가 코드를 제거, 재배열, 다른 instruction 으로 바꿨다면 실험 해석이 틀어질 수 있음
2. 전체 컴파일 계층
[1] CUDA C++ source
사용자가 작성한 kernel.cu
[2] PTX
NVIDIA GPU용 virtual ISA / intermediate representation
[3] SASS
특정 GPU architecture용 실제 machine instruction
[4] Runtime execution
warp scheduler, scoreboard, register file, execution pipeline에서 실행
각 계층의 관찰 관점
| CUDA C++ | 사람이 작성하는 코드 | 알고리즘과 kernel shape 설계 |
| PTX | 가상 GPU assembly / 중간 표현 | compiler가 어떤 의도를 유지했는지 확인 |
| SASS | 실제 GPU instruction | 최종 실행 instruction 확인 |
| Nsight Compute metrics | 실행 결과 계측 | GPU가 어디서 stall되는지 확인 |
3. PTX 란
Paraleel Thread Execution , GPU 용 virtual instruction set
x = x + y;
->
add.rn.f32 %f1, %f1, %f2;
fma 의 경우 ->
fma.rn.f32 %f1, %f1, %f2, %f3;
- 특정 GPU 모델에 완전히 고정된 machine code 가 아님
- virtual ISA 에 가까움
- register 일므도 실제 hardware register 와 1:1 대응이 아님
- ptxas 가 PTX 를 SASS 로 변환
유용하지만 최종 판단은 SASS 로 해야 한다.
4. SASS 란
실제 machine instruction assembly
FADD.FTZ R14, R14, ...
FADD.FTZ R14, R14, ...
FADD.FTZ R14, R14, ...
실제로 GPU 가 실행할 instuction 구조에 가까움
SASS 에서 중요한 점
- 실제 instruction 종류
- 실제 register dependency
- branch 구조
- predicate 사용
- instruction scheduling
- memory load / store 형태
- register reuse hint
- barrier / sync instruction
다음 SASS 확인
FADD.FTZ R14, R14, 1.299999e-05;
FADD.FTZ R14, R14, 1.700000e-05;
FADD.FTZ R14, R14, 1.899999e-05;
이 구조는 명확한 dependency chain
R14 - R14 - R14 - R14
다음 instruction 은 이전 instruction 의 결과 R14 를 다시 입력으로 사용한다.
따라서 scoreboard dependency 가 생긴다.
반대로 다음 구조는 independent accumulator 에 가깝다.
FADD.FTZ R7, R7, ...
FADD.FTZ R8, R8, ...
FADD.FTZ R9, R9, ...
FADD.FTZ R10, R10, ...
이 경우 dependency chain 이 여러 register 로 나뉜다.
R7 chain
R8 chain
R9 chain
R10 chain
하나의 register 결과를 기다리는 동아 다른 register 에 대한 instruction 을 issue 할 수 있다.
5. PTX 와 SASS 의 차이
PTX 와 SASS 의 가장 큰 차이는 추상도
PTX = virtual GPU ISA
SASS = target GPU machine instruction
비유하면 다음과 같다
CUDA C++ = 사람이 작성한 설계도
PTX = GPU용 중간 설계도
SASS = 실제 공장 기계가 수행할 작업 지시서
| 계층 | 중간 표현 | 최종 machine instruction |
| 대상 | virtual NVIDIA GPU | 특정 SM architecture |
| 안정성 | 비교적 문서화되어 있음 | 공식 고수준 문서화는 제한적 |
| register | virtual register | physical에 가까운 allocated register |
| 최적화 전후 | 아직 backend 최적화 전/중간 | 최종 instruction selection 후 |
| 분석 목적 | compiler 의도 확인 | 실제 실행 구조 확인 |
| 성능 해석 | 보조 자료 | 핵심 자료 |
6. arithmetic dependecny probe 에서 확인한 것
네 가지 role 을 비교
independent_fma
independent_add
dependent_fma_chain
dependent_add_chain
JSON 결과에서는 다음 ordering 이 관찰
independent_fma ≈ independent_add
> dependent_fma_chain
> dependent_add_chain
직관적으로 FMA는 multiply-add이므로 ADD보다 무거워 보인다.
하지만 SASS를 확인한 결과, 이 차이는 단순한 FMA vs ADD의 연산 비용 차이로 해석하면 안 된다는 점이 드러났다.
6.1 independent FMA / ADD
SASS 에서 independent FMA 와 independent ADD 는 여러 accumulator register 로 분산되어 있었음
FFMA.FTZ R7, R7, ...
FFMA.FTZ R8, R8, ...
FFMA.FTZ R9, R9, ...
FFMA.FTZ R10, R10, ...
FFMA.FTZ R11, R11, ...
FFMA.FTZ R5, R5, ...
FFMA.FTZ R6, R6, ...
FFMA.FTZ R4, R4, ...
FADD.FTZ R7, R7, ...
FADD.FTZ R8, R8, ...
FADD.FTZ R9, R9, ...
FADD.FTZ R10, R10, ...
FADD.FTZ R11, R11, ...
FADD.FTZ R5, R5, ...
FADD.FTZ R6, R6, ...
FADD.FTZ R4, R4, ...
두 role 모두 다음 구조를 가짐
multiple independent accumulator lanes
이 구조에서는 insturction-level parallelism 이 노출
dependency 가 충분히 분산, scheduler 가 reday instruction 을 계속 찾을 수 있기 때문
6.2 dependent ADD
FADD.FTZ R14, R14, ...
FADD.FTZ R14, R14, ...
FADD.FTZ R14, R14, ...
FADD.FTZ R14, R14, ...
이건 strict single-register dependency chain 이다
R14 → R14 → R14 → R14
이전의 결과를 기다려야 ㅎ마
latency hiding 이 어렵고, progress 가 낮아진다.
6.3 dependent FMA
dependent FMA 도 dependency chain 을 유지한다.
하지만 dependent ADD 처럼 단일 register R14 만 반복 갱신하는 형태는 아니었다.
대표적으로 다음과 같은 구조가 확인
FFMA.FTZ R15, R14, R15, ...
FFMA.FTZ R15, R15, R16, ...
FFMA.FTZ R14, R15, R14, ...
FFMA.FTZ R14, R14, R17, ...
FFMA.FTZ R14, R14, R15, ...
즉 dependency 는 유지된다.
하지만 dependent ADD 와 달리 다음 요소과 섞인다
- R14 / R15 register 교대
- source register setup
- MOV instruction
- instruction spacing 차이
정확한 해석
- dependent_fma_chain 이 dependent_add_chain 보다 높게 나온 것은 FMA 가 ADD 보다 본질적으로 빠르다는 뜻이 아님
- 현재 SASS 에서 dependent ADD 는 더 순수한 single-register FADD chain 이고, dependent FAM 는 R14/R15 를 오가는 FFMA chain 과 MOV/source setup 이 섞인 형태다.
- 따라서 두 role 의 차이는 pure latency difference 가 아니라 effective dependency shape 차이를 보는 것이 맞다 .
7. SASS에서 자주 보이는 instruction 의미
이번 분석에서 본 주요 instruction을 정리하면 다음과 같다.
7.1 FADD
FADD.FTZ R14, R14, ...
floating-point addition이다.
R14 = R14 + constant 또는 R14 = R14 + Rn 형태로 볼 수 있다.
FTZ는 flush-to-zero를 의미한다.
아주 작은 denormal/subnormal 값을 0으로 처리하는 모드다.
성능 분석에서는 보통 다음을 본다.
- destination register가 source로 다시 들어가는가?
- 같은 register chain인가?
- 여러 register로 분산되어 있는가?
7.2 FFMA
FFMA.FTZ R14, R14, R17, ...
floating-point fused multiply-add다.
대략 다음 연산에 해당한다.
R14 = R14 * R17 + constant;
또는 operand 위치에 따라:
dst = a * b + c;
FMA는 multiply와 add를 따로 수행하는 것이 아니라 하나의 fused instruction으로 실행된다.
그래서 FMA를 단순히 “ADD보다 두 배 무거운 연산”으로 보면 안 된다.
7.3 MOV
MOV R17, 0x3f800019;
register에 값을 넣는 instruction이다.
이번 dependent FMA chain에서는 source operand를 준비하는 용도로 MOV가 중간중간 보였다.
이런 instruction은 dependent chain 사이에 끼면서 instruction spacing과 scheduling shape에 영향을 줄 수 있다.
7.4 BRA
BRA 0x5d0;
branch instruction이다.
loop, role 분기, control flow에서 사용된다.
probe 결과를 해석할 때 branch 구조도 중요하다.
왜냐하면 progress counter 기반 실험에서는 loop body에 포함된 branch나 control-flow instruction도 progress에 영향을 줄 수 있기 때문이다.
7.5 S2R
S2R R12, SR_CTAID.X;
special register에서 값을 읽는 instruction이다.
예를 들어 block index, lane id, clock register 같은 값을 읽을 때 사용된다.
clock64() 계열이나 thread/block index 처리에서 관련 instruction이 나타날 수 있다.
8. Nsight Compute와 SASS 분석의 관계
Nsight Compute와 SASS 분석은 경쟁 관계가 아니다.
서로 다른 층위를 본다.
SASS 분석:
이 커널이 실제로 어떤 instruction 구조로 만들어졌는가?
Nsight Compute:
그 instruction 구조를 실행했을 때 GPU가 어디서 막혔는가?
즉:
SASS = 원인 구조 확인
Nsight Compute = 실행 증상 계측
예를 들어 Nsight Compute에서 다음 결과가 나왔다고 하자.
Stall Wait / Short Scoreboard 증가
Eligible Warps Per Scheduler 감소
Issue Slot Utilization 감소
이때 SASS를 같이 보면 원인 추적이 가능해진다.
왜 eligible warp가 부족했는가?
→ SASS에서 R14 → R14 → R14 FADD chain이 있다.
→ ready instruction이 부족해질 수 있다.
반대로 SASS만 보면 실제 stall 정도는 알 수 없다.
R14 chain이 있다.
는 구조적 사실이다.
하지만 그 chain이 실제 실행에서 얼마나 병목이 되었는지는 Nsight Compute metric으로 확인하는 것이 좋다.
따라서 가장 좋은 분석 흐름은 다음이다.
1. JSON / benchmark result
progress ordering 확인
2. SASS inspection
의도한 instruction shape가 실제로 유지되었는지 확인
3. Nsight Compute
stall reason, issue activity, eligible warp, pipe utilization 확인
4. Interpretation
구조와 실행 증상을 연결
9. GPU probing에서 SASS 검증이 중요한 이유
GPU probing의 목적은 단순히 빠르다/느리다를 재는 것이 아니다.
더 중요한 목적은 다음이다.
kernel shape → hardware response
즉 특정 kernel 구조를 GPU에 넣었을 때, GPU가 어떤 반응을 보이는지 측정하는 것이다.
그런데 여기서 가장 위험한 부분은 이것이다.
내가 의도한 kernel shape가
실제로 GPU에 전달되지 않았을 수 있다.
예를 들어 dependent chain을 만들었다고 생각했는데 compiler가 그것을 제거했다면, 실험 결과는 무의미해질 수 있다.
따라서 probe 문서에는 가능하면 다음 섹션이 들어가야 한다.
SASS Validation
여기서 확인할 것은 다음이다.
- 의도한 instruction이 실제로 생성되었는가?
- dependent chain이 register dependency로 유지되는가?
- independent accumulator가 여러 register로 분산되는가?
- memory access pattern이 의도한 주소 형태로 유지되는가?
- loop body가 예상보다 많이 변형되지 않았는가?
이번 arithmetic_dependency_probe는 좋은 예시다.
Result:
dependent_add_chain이 가장 낮은 progress를 보였다.
SASS Validation:
dependent ADD가 실제로 R14 단일 FADD chain으로 생성되었다.
Interpretation:
낮은 progress는 compiler 착시가 아니라,
강한 single-register dependency shape와 연결된다.
10. SASS 분석 기본 절차
Windows + CUDA 12.6 기준으로 정리하면 다음과 같다.
10.1 SASS 덤프
& "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6\bin\cuobjdump.exe" --dump-sass "build\CMakeFiles\probe_runner_arithmetic_dependency.dir\src\probes\arithmetic_dependency_probe\kernel.cu.obj" > "results\raw\arithmetic_dependency_probe.kernel.sass.txt"
10.2 PTX 덤프
& "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6\bin\cuobjdump.exe" --dump-ptx "build\CMakeFiles\probe_runner_arithmetic_dependency.dir\src\probes\arithmetic_dependency_probe\kernel.cu.obj" > "results\raw\arithmetic_dependency_probe.kernel.ptx.txt"
10.3 검색
PowerShell에서는 findstr보다 Select-String이 편하다.
Select-String -Path "results\raw\arithmetic_dependency_probe.kernel.sass.txt" -Pattern "Function|FFMA|FADD|FADD32I|FMUL" -Context 2,2
산술 instruction만 보려면:
Select-String -Path "results\raw\arithmetic_dependency_probe.kernel.sass.txt" -Pattern "FFMA|FADD|FADD32I|FMUL" -Context 2,2
branch나 special register까지 보려면:
Select-String -Path "results\raw\arithmetic_dependency_probe.kernel.sass.txt" -Pattern "FFMA|FADD|BRA|S2R|CS2R|BSYNC|BAR|LDG|STG" -Context 2,2
11. SASS 분석 체크리스트
probe를 분석할 때는 다음 순서로 보면 좋다.
11.1 kernel 함수 찾기
Function : ...
이 줄을 먼저 찾는다.
이번 경우는 arithmetic_dependency_kernel이 확인되었다.
11.2 target architecture 확인
code for sm_86
이런 식으로 어떤 architecture용 SASS인지 확인한다.
이는 중요하다.
SM80, SM86, SM89, SM90에 따라 instruction scheduling과 사용 가능한 instruction이 달라질 수 있기 때문이다.
11.3 instruction 종류 확인
FFMA
FADD
FMUL
IADD
IMAD
LDG
STG
BRA
S2R
내가 의도한 instruction이 실제로 존재하는지 확인한다.
11.4 register dependency 확인
가장 중요하다.
dependent chain이라면:
FADD R14, R14, ...
FADD R14, R14, ...
FADD R14, R14, ...
같은 형태여야 한다.
independent accumulator라면:
FADD R7, R7, ...
FADD R8, R8, ...
FADD R9, R9, ...
처럼 register가 분산되어야 한다.
11.5 loop body와 branch 확인
progress 기반 probe에서는 loop body가 매우 중요하다.
- loop마다 instruction이 몇 개 들어가는가?
- branch가 어디 있는가?
- clock 체크가 어디 있는가?
- role별 code path가 비슷한가?
이 차이가 progress 차이에 섞일 수 있다.
12. PTX/SASS를 볼 때 주의할 점
12.1 PTX는 최종 실행 코드가 아니다
PTX에 어떤 instruction이 있다고 해서 SASS에서도 같은 구조가 유지된다고 단정하면 안 된다.
최종 확인은 SASS 기준이다.
12.2 SASS도 성능 metric 자체는 아니다
SASS는 구조를 보여준다.
하지만 실제 stall 비율, throughput, occupancy는 실행 계측이 필요하다.
그 역할은 Nsight Compute가 한다.
12.3 register 이름은 source code 변수와 직접 대응되지 않는다
CUDA 코드의 x, acc0, acc1이 SASS에서 어떤 register가 될지는 compiler가 결정한다.
따라서 source variable 이름으로 추적하기보다는, register dependency pattern을 봐야 한다.
12.4 compiler flag에 따라 결과가 달라질 수 있다
예를 들어 다음 옵션들은 SASS에 영향을 줄 수 있다.
-O0 / -O3
-use_fast_math
--fmad=false
-lineinfo
maxrregcount
architecture target: sm_86, sm_89, sm_90
따라서 SASS 분석 결과는 반드시 빌드 조건과 함께 기록해야 한다.
13. lineinfo를 켜면 좋은 이유
SASS만 보면 어느 instruction이 kernel.cu의 어느 줄에서 왔는지 추적하기 어렵다.
이때 -lineinfo를 켜면 Nsight Compute나 일부 disassembly에서 source line mapping이 더 좋아진다.
CMake에 다음을 추가할 수 있다.
target_compile_options(probe_runner_arithmetic_dependency PRIVATE
$<$<COMPILE_LANGUAGE:CUDA>:-lineinfo>
)
또는 전체 CUDA compile에 적용하려면:
add_compile_options(
$<$<COMPILE_LANGUAGE:CUDA>:-lineinfo>
)
주의할 점은 -G와 다르다는 것이다.
-lineinfo:
최적화는 유지하면서 source line 정보를 추가한다.
-G:
device debug mode에 가깝고 최적화를 크게 바꿀 수 있다.
성능 분석용으로는 조심해야 한다.
성능 probe에서는 보통 -lineinfo는 괜찮지만, -G는 피하는 것이 좋다.
14. 이번 프로젝트에서의 권장 분석 루틴
gpu-probing-lab-arithmetic에서는 앞으로 각 probe마다 다음 구조로 분석하면 좋다.
1. Run probe
results/raw/*.json 생성
2. Summarize progress signature
role별 평균, ratio, ordering 정리
3. Dump SASS
kernel.cu.obj 또는 exe 대상 cuobjdump
4. Validate instruction shape
dependent chain / independent accumulator / memory pattern 확인
5. Optionally run Nsight Compute
stall reason, eligible warp, issue utilization 확인
6. Write interpretation
kernel shape → SASS shape → hardware response 연결
이 흐름은 Atlas 문서 구조로도 잘 맞는다.
Observation
- JSON result
SASS Validation
- instruction shape confirmed
Execution Interpretation
- hardware response explained
Codegen Implication
- heuristic / cost model implication
15. 최종 정리
PTX와 SASS는 CUDA kernel을 더 낮은 층위에서 이해하기 위한 도구다.
PTX는 중간 표현이다.
SASS는 실제 GPU instruction이다.
Nsight Compute는 실행 결과 계측이다.
이번 arithmetic dependency probe에서 SASS 분석은 다음 사실을 확인해 주었다.
1. independent FMA/ADD는 여러 accumulator register로 분산되어 있었다.
2. dependent ADD는 R14 단일 FADD dependency chain으로 생성되었다.
3. dependent FMA는 R14/R15를 오가는 FFMA dependency chain으로 생성되었다.
4. 따라서 JSON progress ordering은 실제 instruction shape와 일관된다.
가장 중요한 결론은 이것이다.
GPU probing에서 SASS 분석은 선택 사항이 아니라,
실험 자극이 실제로 의도한 형태로 GPU에 전달되었는지 검증하는 단계다.
그리고 Nsight Compute와 함께 쓰면 더 강해진다.
SASS:
무슨 instruction 구조가 실행되었는가?
Nsight Compute:
그 구조가 실행될 때 GPU는 어디서 막혔는가?
따라서 앞으로의 probe 분석은 다음 구조로 가져가는 것이 좋다.
'GPU Probing Lab' 카테고리의 다른 글
| Controlled Arithmetic Chain Probe 문서화 - chain length, progress scaling, SASS shape 변화 (0) | 2026.05.19 |
|---|---|
| Controlled Arithmetic Chain Probe 결과 정리 - dependent FMA vs dependent ADD 해석 검증 (0) | 2026.05.19 |
| Arithmetic Dependency Probe SASS 분석 문서 (0) | 2026.05.18 |
| GPU Probing 결과를 코드 생성 규칙으로 연결하는 구조 (0) | 2026.05.13 |
| Warp Progress Signature Probing - Chapter 1. Workload Pattern에서 Transient Phase까지 (0) | 2026.05.13 |