1. 목적
SASS 프로브의 목적은 단순히 GPU 기계어를 출력해 보는 것이 아니다.
핵심 목적은 다음과 같다.
통제된 CUDA 프로그램을 작성하고, 실제 생성된 SASS와 실행 결과를 함께 분석해 GPU의 명령어 latency, throughput, 자원 충돌, 메모리 구조와 같은 실행 특성을 추론한다.
전체 과정은 다음과 같다.
하드웨어 가설 설정
↓
프로브 코드 작성
↓
컴파일
↓
PTX·SASS 검증
↓
실제 GPU 실행
↓
cycle·성능 지표 수집
↓
대조 실험과 변수 sweep
↓
하드웨어 행동 모델 작성
SASS는 이 과정의 중간 결과다.
SASS
→ 어떤 기계어가 생성됐는지 확인
실행 결과
→ 그 기계어가 실제로 어떻게 동작했는지 확인
따라서 SASS와 실행 측정을 반드시 함께 사용해야 한다.
2. 하나의 실험은 하나의 질문만 다룬다
좋은 프로브는 하나의 주요 변수만 바꾼다.
예를 들어 FFMA latency를 확인하려면 다음 두 조건만 비교한다.
실험 A
하나의 accumulator를 사용하는 의존 FFMA 사슬
실험 B
여러 accumulator를 사용하는 독립 FFMA 명령열
가능한 한 다음 조건은 동일하게 유지한다.
명령어 종류
명령어 수
반복 횟수
block 수
thread 수
컴파일 옵션
타이머 방식
입력값
출력 저장 방식
두 실험 사이에서 달라지는 것은 오직 다음이어야 한다.
명령어 사이의 데이터 의존성
변수가 여러 개 동시에 바뀌면 결과의 원인을 분리하기 어렵다.
3. 1단계: 하드웨어 가설 설정
먼저 무엇을 알아내려는지 문장으로 작성한다.
예:
가설 1:
연속된 FFMA가 동일한 accumulator를 사용하면
결과 의존 latency가 실행 시간에 직접 나타난다.
가설 2:
여러 독립 accumulator를 사용하면
FFMA latency를 다른 명령어 발행으로 숨길 수 있다.
또 다른 가설의 예시는 다음과 같다.
FP32 연산과 INT 연산은 서로 다른 실행 자원을 사용할 수 있다.
shared memory는 특정 stride에서 bank conflict를 발생시킨다.
register 사용량 증가가 일정 지점을 넘으면 occupancy가 감소한다.
working set이 특정 크기를 넘으면 cache latency가 증가한다.
가설은 가능한 한 관측 가능한 형태로 작성해야 한다.
좋지 않은 표현:
GPU 내부에는 여러 연산기가 존재한다.
더 좋은 표현:
FP32 FFMA와 IADD3를 혼합했을 때
각각을 단독으로 실행한 경우보다 처리량 감소가 작다면,
두 명령이 일부 독립 실행 자원을 사용하는 행동으로 해석할 수 있다.
4. 2단계: 프로브 코드 작성
프로브 코드는 다음 원칙을 따라야 한다.
4.1 측정 대상 명령어를 명확하게 만든다
컴파일러가 다른 명령어로 바꾸지 않도록 PTX inline assembly를 사용할 수 있다.
asm volatile(
"fma.rn.f32 %0, %1, %2, %3;"
: "=f"(result)
: "f"(a), "f"(b), "f"(c));
하지만 PTX를 직접 작성해도 최종적으로 어떤 SASS가 생성되는지는 별도로 확인해야 한다.
PTX fma
→ 반드시 SASS FFMA가 된다고 가정하지 않는다.
4.2 계산 제거를 방지한다
계산 결과가 사용되지 않으면 컴파일러가 전체 연산을 제거할 수 있다.
따라서 최종 결과를 global memory에 저장한다.
output[0] = accumulator;
출력값은 두 가지 역할을 한다.
컴파일러의 dead code elimination 방지
실험 결과의 checksum 검증
4.3 반복 횟수를 충분히 크게 한다
타이머 읽기와 초기화 비용을 희석하기 위해 동일 명령을 많이 반복한다.
명령어 수가 적음
→ 타이머와 분기 비용의 비중이 큼
명령어 수가 많음
→ 명령어 자체 비용이 전체 측정을 지배
예:
4096 outer iterations
× 32 instructions
= 131072 target instructions
4.4 측정 구간을 작게 유지한다
측정 구간 안에는 가능한 한 목표 명령어만 있어야 한다.
이상적인 구조:
clock64
목표 명령 반복
clock64
실제 반복문에서는 다음 명령이 추가될 수 있다.
IADD3
ISETP
BRA
이러한 오버헤드는 이후 대조군으로 측정한다.
5. 3단계: 컴파일 환경 기록
마이크로벤치마크 결과는 GPU뿐 아니라 컴파일러에도 영향을 받는다.
따라서 다음 정보를 기록해야 한다.
GPU 모델
compute capability
GPU driver 버전
CUDA Toolkit 버전
nvcc 버전
ptxas 버전
cuobjdump 버전
nvdisasm 버전
Nsight Compute 버전
컴파일 옵션
예:
nvcc --version > results\nvcc_version.txt
cuobjdump --version > results\cuobjdump_version.txt
nvdisasm --version > results\nvdisasm_version.txt
ncu --version > results\ncu_version.txt
nvidia-smi > results\gpu_environment.txt
컴파일 명령 자체도 저장한다.
build_command.txt
예:
nvcc `
-O3 `
-lineinfo `
-Xptxas=-v `
-arch=sm_86 `
src\probe_ffma.cu `
-o build\probe_ffma.exe `
2>&1 |
Tee-Object build\probe_ffma_build.txt
6. 4단계: PTX 확인
PTX는 CUDA 코드와 실제 SASS 사이의 중간 표현이다.
cuobjdump --dump-ptx build\probe_ffma.exe `
> results\probe_ffma.ptx.txt
PTX에서 확인할 내용은 다음과 같다.
목표 연산이 존재하는가
데이터 타입이 올바른가
예상하지 않은 변환 명령이 존재하는가
분기와 반복문이 어떻게 표현됐는가
load와 store가 추가됐는가
그러나 PTX는 최종 GPU 명령어가 아니다.
CUDA source
↓
PTX
↓
GPU별 SASS
따라서 PTX 확인만으로 실험 구조를 확정하면 안 된다.
7. 5단계: SASS 원본 출력
최종적으로 실제 GPU가 실행할 SASS를 확인한다.
cuobjdump --dump-sass build\probe_ffma.exe 2>&1 |
Tee-Object results\probe_ffma_full.sass.txt
SASS 원본은 반드시 보관한다.
필터링된 결과만 저장하면 주변 명령어를 놓칠 수 있다.
필터링본
→ 빠른 확인용
전체 SASS
→ 정확한 분석과 재검증용
필터링본은 다음처럼 추가로 만든다.
cuobjdump --dump-sass build\probe_ffma.exe |
Select-String `
-Pattern "Function|FFMA|FADD|IADD3|ISETP|BRA|LD|ST|CS2R" |
Set-Content results\probe_ffma_filtered.sass.txt
8. 6단계: SASS에서 확인할 항목
8.1 목표 명령어 존재 여부
소스에서 의도한 연산이 실제 SASS에 존재하는지 확인한다.
PTX fma.rn.f32
→ SASS FFMA
컴파일러가 다음과 같이 바꿨을 가능성도 확인해야 한다.
연산 제거
상수 folding
다른 명령어로 치환
여러 명령 결합
load·store 추가
8.2 명령어 개수
정적 명령어 수가 코드의 의도와 맞는지 확인한다.
예:
루프 본문 FFMA 수: 32
outer 반복 횟수: 4096
동적 FFMA 수:
32 × 4096 = 131072
실행 결과를 명령어 수로 나눌 때 이 값이 필요하다.
8.3 레지스터 의존 관계
명령어 operand를 보고 데이터 의존성을 확인한다.
의존 사슬:
FFMA R9, R9, R0, ...
FFMA R9, R9, R0, ...
FFMA R9, R9, R0, ...
모든 명령이 이전 R9 결과를 기다린다.
독립 사슬:
FFMA R12, R12, R7, ...
FFMA R11, R11, R7, ...
FFMA R10, R10, R7, ...
FFMA R9, R9, R7, ...
accumulator 레지스터가 서로 다르므로 명령 사이의 독립성이 존재한다.
현재 확인된 SASS에서도 의존 커널은 동일한 R9를 반복 사용하고, 독립 커널은 여러 accumulator를 교대로 사용하도록 생성됐다.
8.4 측정 루프 경계
타이머가 어느 위치에서 읽히는지 확인한다.
CS2R ..., SR_CLOCKLO
다음 사항을 봐야 한다.
타이머 시작이 초기화 뒤에 있는가
타이머 종료가 목표 명령 뒤에 있는가
결과 store가 측정 구간 밖에 있는가
예상하지 않은 명령이 측정 구간에 포함됐는가
8.5 루프 구조
다음 명령을 통해 반복 구조를 확인한다.
IADD3
ISETP
BRA
확인할 내용:
안쪽 루프가 전개됐는가
바깥 루프가 유지됐는가
반복 횟수가 예상과 일치하는가
숨겨진 분기가 추가됐는가
8.6 예상하지 않은 메모리 명령
측정 루프 내부에 다음 명령이 있는지 확인한다.
LDG
LDS
LDL
STG
STS
STL
FFMA latency를 측정하는데 반복문 안에 local memory load가 존재한다면 register spill이 발생했을 수 있다.
순수 FFMA 프로브
+
local memory load/store
=
실험 오염
9. 7단계: 자원 사용량 확인
SASS만 보고는 레지스터 spill과 전체 자원 사용량을 놓칠 수 있다.
9.1 ptxas 출력
nvcc `
-O3 `
-lineinfo `
-Xptxas=-v `
-arch=sm_86 `
src\probe_ffma.cu `
-o build\probe_ffma.exe `
2>&1 |
Tee-Object results\probe_ffma_build.txt
확인 항목:
Used registers
stack frame
spill stores
spill loads
constant memory
가장 중요한 조건은 다음이다.
spill stores = 0
spill loads = 0
9.2 리소스 사용량 출력
cuobjdump --dump-resource-usage build\probe_ffma.exe `
> results\probe_ffma_resource_usage.txt
커널별로 확인한다.
register 수
shared memory
local memory
stack
constant memory
accumulator 수를 늘리는 실험에서는 레지스터 수가 함께 증가하므로 반드시 기록해야 한다.
10. 8단계: 상세 SASS 분석
nvdisasm을 사용하면 cuobjdump보다 더 자세한 정보를 볼 수 있다.
먼저 cubin을 추출한다.
Push-Location build
cuobjdump --extract-elf all probe_ffma.exe
Pop-Location
10.1 소스 줄 연결
nvdisasm `
-c `
-g `
-sf `
build\<cubin-file> `
> results\probe_ffma_lineinfo.sass.txt
이를 통해 다음을 연결할 수 있다.
CUDA 소스 줄
→ PTX
→ SASS 명령어
10.2 명령어 인코딩과 register life range
nvdisasm `
-c `
-hex `
-plr `
-sf `
build\<cubin-file> `
> results\probe_ffma_detailed.sass.txt
확인할 수 있는 내용:
명령어 인코딩
레지스터 생명주기
accumulator가 루프 전체에서 유지되는지
임시 레지스터가 얼마나 생성되는지
단, SASS 제어 비트와 명령어 간 정적 간격만으로 실제 latency를 확정해서는 안 된다.
SASS 제어 정보
→ 컴파일러가 만든 실행 제약
실제 cycle 측정
→ 하드웨어가 실제로 보인 실행 시간
11. 9단계: 실행 결과 수집
한 번의 결과만 저장하지 않고 여러 번 반복한다.
권장 과정:
warm-up 5~10회
측정 50~100회
각 실행 결과 저장
통계 계산
원시 결과는 CSV 형태가 적합하다.
run,kernel,total_instructions,total_cycles,cycles_per_instruction,checksum
0,dependent,131072,524610,4.002457,1.027639627
1,dependent,131072,524602,4.002396,1.027639627
2,independent_8,131072,131401,1.002510,8.221864700
요약 통계는 별도 파일에 저장한다.
sample count
minimum
median
mean
maximum
standard deviation
p5
p95
평균 하나만 보는 것은 충분하지 않다.
minimum
→ 외부 방해가 적었던 실행 후보
median
→ 대표적인 실행값
standard deviation
→ 측정 안정성
maximum
→ 스케줄링·클럭·시스템 간섭 후보
12. 10단계: 대조 실험
프로브 결과에는 목표 명령어 외의 비용이 포함될 수 있다.
따라서 대조군이 필요하다.
12.1 타이머 대조군
clock64
clock64
측정:
timer read overhead
12.2 빈 루프 대조군
목표 명령어를 제거하고 동일한 반복문 구조만 유지한다.
IADD3
ISETP
BRA
측정:
loop overhead
branch overhead
보정값:
corrected_cycles
=
probe_cycles
-
empty_loop_cycles
단, 컴파일러가 빈 루프를 제거할 수 있으므로 빈 루프 SASS도 확인해야 한다.
12.3 명령어 종류 대조군
동일한 구조에서 다른 명령어를 실행한다.
FFMA 의존 사슬
IADD3 의존 사슬
FADD 의존 사슬
이를 통해 측정 방식 자체가 특정 명령에만 이상하게 작동하는지 확인할 수 있다.
13. 11단계: 명령어 수 sweep
하나의 반복 횟수만 측정하면 고정 오버헤드를 분리하기 어렵다.
다음처럼 명령어 수를 바꾼다.
1024
4096
16384
65536
131072
262144
모델:
T(N) = L × N + C
여기서:
N = 목표 명령어 수
L = 명령어 하나당 증가하는 cycle
C = 타이머·초기화 등의 고정 비용
여러 측정값을 직선으로 회귀한다.
출력:
slope
intercept
R²
해석:
slope
→ 명령어당 cycle 추정값
intercept
→ 고정 오버헤드
R²
→ 측정값이 선형 모델과 얼마나 잘 맞는지
단순히 total_cycles / instruction_count를 계산하는 것보다 더 신뢰도가 높다.
14. 12단계: accumulator 수 sweep
독립 명령어 수를 변화시킨다.
accumulator 1개
accumulator 2개
accumulator 4개
accumulator 8개
accumulator 16개
기록 항목:
accumulators,registers,cycles_per_instruction,spill_loads,spill_stores
1,10,4.00,0,0
2,11,2.02,0,0
4,13,1.03,0,0
8,17,1.01,0,0
16,29,1.02,0,0
이를 통해 확인하는 내용은 다음과 같다.
몇 개의 독립 명령이 있어야 latency가 숨겨지는가
어느 지점부터 처리량 증가가 멈추는가
accumulator 증가가 register pressure를 만드는가
spill이 발생하면 성능이 어떻게 변하는가
15. 13단계: warp 수 sweep
단일 warp 실험과 여러 warp 실험은 서로 다른 것을 측정한다.
단일 warp
명령어 의존 latency
단일 warp issue 특성
여러 warp
warp scheduler의 latency hiding
SM 전체 처리량
occupancy 영향
실행 구성을 변화시킨다.
<<<1, 1>>>
<<<1, 32>>>
<<<1, 64>>>
<<<1, 128>>>
<<<SM 수, 128>>>
기록 항목:
block 수
thread 수
활성 warp 수
총 명령어 수
cycles per instruction
instructions per cycle
단일 thread 결과를 GPU 전체 throughput으로 해석하면 안 된다.
16. 14단계: Nsight Compute 교차 검증
실행 cycle만으로는 대기 원인을 완전히 분리하기 어렵다.
Nsight Compute 보고서를 함께 수집한다.
ncu `
--set full `
--export results\probe_ffma_profile `
--force-overwrite `
.\build\probe_ffma.exe
원본 보고서:
probe_ffma_profile.ncu-rep
CSV 출력:
ncu `
--import results\probe_ffma_profile.ncu-rep `
--page raw `
--csv `
> results\probe_ffma_ncu_raw.csv
SASS와 metric 연결:
ncu `
--import results\probe_ffma_profile.ncu-rep `
--page source `
--print-source sass `
> results\probe_ffma_ncu_sass.txt
확인할 범주는 다음과 같다.
실행된 SASS 명령어 수
FP32 pipeline 활동
warp stall reason
dependency 관련 stall
scheduler issue 상태
achieved occupancy
register 사용량
local memory 접근
SM clock
metric 이름은 GPU와 Nsight Compute 버전에 따라 달라질 수 있으므로 raw 결과 전체를 저장하는 것이 안전하다.
17. 15단계: 결과 해석
17.1 SASS만으로 알 수 있는 것
어떤 명령어가 생성됐는가
명령어 수가 몇 개인가
어떤 레지스터를 사용하는가
데이터 의존성이 존재하는가
루프가 어떻게 구성됐는가
load와 store가 추가됐는가
17.2 실행 측정으로 알 수 있는 것
전체 실행 cycle
명령어당 관측 cycle
의존성과 독립성의 시간 차이
명령어 수 증가에 따른 기울기
accumulator 수에 따른 처리량 변화
17.3 프로파일러로 보완할 수 있는 것
pipeline 활동
stall 원인
실행 명령어 수
occupancy
register 및 memory 영향
세 결과를 결합해야 한다.
SASS
→ 실험 구조 검증
cycle 측정
→ 실행 행동 관측
성능 counter
→ 행동 원인에 대한 추가 단서
18. 결론 표현의 강도
하드웨어 프로브 결과는 증거 수준에 따라 표현해야 한다.
SASS만 확인한 단계
의존 FFMA 사슬이 실제 SASS에 생성됐다.
가능한 표현:
latency를 측정하기 위한 명령어 의존 구조가 기계어에 의도대로 반영됐다.
아직 말할 수 없는 표현:
FFMA latency는 4 cycle이다.
실행 결과까지 확인한 단계
의존 FFMA에서 약 4 cycles/instruction이 관측됐다.
가능한 표현:
해당 실행 조건에서 FFMA 의존 사슬은 명령어당 약 4 cycle의 실행 간격을 보였다.
대조군과 sweep까지 확인한 단계
빈 루프 보정
명령어 수 회귀
accumulator sweep
반복 측정
가능한 표현:
여러 명령어 사슬 길이에 대한 회귀와 반복문 오버헤드 보정 결과, 해당 GPU에서 FFMA 의존 사슬의 관측 latency는 약 4 cycle로 추정됐다.
프로파일러 교차 검증까지 완료한 단계
cycle 결과
+
dependency stall
+
FP32 pipeline 활동
가능한 표현:
SASS 의존 구조, 실행 cycle, stall metric이 일관된 결과를 보여 FFMA 결과 의존 latency가 약 4 cycle이라는 해석을 지지한다.
여전히 다음과 같이 표현하는 것이 적절하다.
물리 회로의 절대 latency
보다는
해당 GPU와 실행 조건에서 관측된
FFMA 의존 사슬 latency
19. 자동화할 출력
SASS_probe는 최종적으로 다음 정보를 자동 생성하는 방향으로 확장할 수 있다.
정적 분석
kernel name
target architecture
opcode histogram
target instruction count
loop bound
accumulator register set
dependency chain
load/store 존재 여부
branch 수
timer 위치
자원 분석
registers per thread
shared memory
local memory
stack
spill loads
spill stores
실행 분석
total cycles
cycles per instruction
minimum
median
mean
standard deviation
checksum
sweep 분석
instruction count slope
fixed overhead
accumulator saturation point
warp scaling
register pressure transition
프로파일러 분석
executed instructions
pipeline activity
stall reasons
occupancy
clock
memory traffic
20. 권장 실험 폴더 구조
results/
└─ exp003_ffma_probe/
├─ metadata.json
├─ build_command.txt
├─ run_command.txt
│
├─ environment/
│ ├─ gpu_environment.txt
│ ├─ nvcc_version.txt
│ ├─ cuobjdump_version.txt
│ ├─ nvdisasm_version.txt
│ └─ ncu_version.txt
│
├─ binary/
│ ├─ probe_ffma.ptx.txt
│ ├─ probe_ffma_full.sass.txt
│ ├─ probe_ffma_filtered.sass.txt
│ ├─ probe_ffma_detailed.sass.txt
│ ├─ probe_ffma_resource_usage.txt
│ └─ probe_ffma_build.txt
│
├─ runtime/
│ ├─ runtime_raw.csv
│ ├─ runtime_summary.txt
│ ├─ instruction_count_sweep.csv
│ ├─ accumulator_sweep.csv
│ └─ warp_sweep.csv
│
├─ profiler/
│ ├─ probe_ffma_profile.ncu-rep
│ ├─ probe_ffma_ncu_raw.csv
│ └─ probe_ffma_ncu_sass.txt
│
└─ conclusion.md
21. 전체 방법 요약
SASS 기반 GPU 프로빙의 핵심 과정은 다음과 같다.
1. 하나의 하드웨어 가설을 세운다.
2. 하나의 주요 변수만 변화하는 프로브를 작성한다.
3. 컴파일 환경과 옵션을 기록한다.
4. PTX를 확인한다.
5. 최종 SASS를 확인한다.
6. 목표 명령어, 개수, 레지스터 의존성,
루프 구조와 load/store를 검증한다.
7. 레지스터, spill, local memory 사용량을 확인한다.
8. 실제 GPU에서 여러 번 실행해 raw cycle을 저장한다.
9. 타이머와 빈 루프 대조군으로 오버헤드를 추정한다.
10. 명령어 수, accumulator 수, warp 수를 변화시킨다.
11. Nsight Compute metric으로 실행 결과를 교차 검증한다.
12. 확인된 사실과 추론을 분리해 결론을 작성한다.
가장 중요한 원칙은 다음과 같다.
SASS는 실험 장치가 의도대로 만들어졌는지 확인하는 수단이고, 실제 실행 측정은 그 장치를 이용해 하드웨어의 행동을 관측하는 과정이다.
따라서 다음 세 요소가 모두 필요하다.
정적 기계어 분석
+
동적 실행 측정
+
대조 실험과 교차 검증
SASS_probe의 목표는 기계어를 단순 출력하는 데 있지 않다.
최종 목표는 다음과 같다.
통제된 프로그램과 실제 기계어, 실행 시간, 성능 카운터를 결합해 소프트웨어 최적화와 컴파일러 비용 모델에 사용할 수 있는 GPU 행동 모델을 구축한다.
'SASS_Probe' 카테고리의 다른 글
| 소스 코드에서 하드웨어 실행까지 이어지는 추적 가능한 분석 모델의 구축 (0) | 2026.07.17 |
|---|---|
| SASS 만으로 명령어 latency 를 확정할 수 없는 이유 - ffma 실험 기준 (0) | 2026.07.09 |
| 공개되지 않은 하드웨어 특성을 실행으로 추론하는 방법 (0) | 2026.07.09 |
| SASSScope exp002 실험 과정 정리 (0) | 2026.07.07 |
| SASSScope Experiment 002 - 4→2 Linear의 Bias / ReLU 분리 관찰 (0) | 2026.07.07 |