MCP HubMCP Hub
스킬 목록으로 돌아가기

analyze-kernel-bottleneck

pjt222
업데이트됨 Yesterday
1 조회
17
2
17
GitHub에서 보기
기타general

정보

이 스킬은 GPU 커널을 분석하여 루프라인 분석과 점유율 메트릭을 사용해 컴퓨팅 제한, 메모리 제한, 레이턴시 제한으로 분류합니다. 타일링이나 더블 버퍼링과 같은 특정 최적화 전략을 추천하는 의사결정 매트릭스를 제공합니다. 성능 튜닝 작업을 안내하는 고급 CUDA 커널 프로파일링에 활용하세요.

빠른 설치

Claude Code

추천
기본
npx skills add pjt222/agent-almanac -a claude-code
플러그인 명령대체
/plugin add https://github.com/pjt222/agent-almanac
Git 클론대체
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/analyze-kernel-bottleneck

Claude Code에서 이 명령을 복사하여 붙여넣어 스킬을 설치하세요

문서

Analyze Kernel Bottleneck

Identifica sistemáticamente si un kernel de GPU está limitado por cómputo, memoria o latencia midiendo el rendimiento de referencia, clasificándolo en el roofline, calculando la ocupación y la razón cómputo/carga por tile, inspeccionando la mezcla de instrucciones SASS y los códigos de stall, verificando el acantilado de memoria compartida, y aplicando una matriz de decisión para seleccionar la estrategia de optimización correcta.

Cuándo Usar

  • Antes de optimizar cualquier kernel CUDA -- establecer la línea base y clasificar el tipo de cuello de botella
  • Después de escribir una primera versión funcional de un kernel para identificar la ruta de optimización
  • Cuando un kernel rinde por debajo de las expectativas relativas al pico teórico
  • Al decidir entre cp.async, tiles más grandes o reestructuración algorítmica

Entradas

  • Requerido: Kernel compilado (.cubin o fuente .cu con comando de build)
  • Requerido: Arnés de benchmark que lanza el kernel con temporización por eventos CUDA
  • Requerido: Dimensiones del problema (p. ej., M, N, K para GEMM; seq_len, heads, head_dim para attention)
  • Opcional: Arquitectura de GPU objetivo (predeterminado: GA104 / sm_86 / RTX 3070 Ti)
  • Opcional: Porcentaje de utilización pico esperado para comparación
  • Opcional: Datos de profiling previos (informes de Nsight Compute)

Procedimiento

Paso 1: Medir Rendimiento de Referencia

Ejecutar el kernel con eventos CUDA (BenchTimer), registrar tiempo en milisegundos. Calcular métricas efectivas de rendimiento:

  1. Compilar el kernel si aún no está construido:
    nvcc --cubin -arch=sm_86 -O2 -o kernel.sm_86.cubin kernel.cu
    nvcc -arch=sm_86 -O2 -o bench bench.cu -lcuda -I../../phase2/common
    
  2. Ejecutar con tamaños de problema representativos, asegurando que las ejecuciones de calentamiento precedan a la medición:
    ./bench 4096 4096 4096
    
  3. Registrar el tiempo del kernel en ms desde eventos CUDA (no reloj de pared).
  4. Calcular GFLOPS efectivos y ancho de banda efectivo:
    • GEMM: effective_gflops = (2 * M * N * K) / (time_ms / 1000) / 1e9
    • Kernels limitados por ancho de banda: effective_bw = total_bytes / (time_ms / 1000) / 1e9
    • Flash Attention: effective_gflops = (4 * batch * heads * seq_len^2 * head_dim) / (time_ms / 1000) / 1e9

Esperado: Números de referencia: tiempo del kernel en ms, GFLOPS efectivos y ancho de banda efectivo.

En caso de fallo: Verificar que el kernel se lanza sin error (macro CHECK_CU). Verificar que las ejecuciones de calentamiento preceden a la medición. Asegurar que las dimensiones del problema son lo suficientemente grandes para saturar la GPU (problemas pequeños pueden tener cuello de botella en la sobrecarga de lanzamiento).

Paso 2: Clasificar en el Roofline

Calcular la intensidad aritmética y compararla con el punto de equilibrio de la máquina para clasificar el kernel:

  1. Calcular intensidad aritmética: AI = FLOPs / bytes_loaded_from_global_memory. Contar solo bytes únicos cargados desde DRAM (no memoria compartida ni reuso de registros).
  2. Buscar el punto de equilibrio de la máquina: balance = peak_compute / peak_bandwidth.
  3. Clasificar: Si AI < balance, el kernel está limitado por memoria. Si AI > balance, el kernel está limitado por cómputo.

Valores de Referencia GA104 (RTX 3070 Ti):

RecursoPicoUnidad
FP32 FFMA21.7TFLOPS
FP16 Tensor Core (HMMA)174TFLOPS
INT8 Tensor Core (IMMA)696TOPS
Ancho de banda DRAM608GB/s
Caché L24MB
SMs48

Puntos de Equilibrio Derivados:

PrecisiónPunto de Equilibrio (FLOP/byte)
FP32 FFMA21700 / 608 = 35.7
FP16 TC174000 / 608 = 286.2
INT8 TC696000 / 608 = 1144.7
  1. Calcular fracción alcanzada: attained = effective_throughput / peak_throughput. Si está limitado por memoria: comparar el ancho de banda efectivo con 608 GB/s. Si está limitado por cómputo: comparar GFLOPS efectivos con el pico relevante.

Esperado: Clasificación como limitado por cómputo, memoria o latencia (baja ocupación que causa que ni el cómputo ni la memoria se saturen) con justificación numérica.

En caso de fallo: Recontar bytes. Atención a re-lecturas redundantes (p. ej., 9x en conv2d directo sin im2col). Si ni el cómputo ni la memoria están saturados, el kernel probablemente está limitado por latencia (ver Paso 3).

Paso 3: Calcular la Ocupación

Determinar warps activos por SM a partir de la configuración de lanzamiento y el uso de recursos:

  1. Extraer uso de recursos:
    nvcc --cubin -arch=sm_86 -O2 --resource-usage -o kernel.sm_86.cubin kernel.cu 2>&1 | grep -E 'registers|smem'
    
  2. Desde la configuración de lanzamiento: warps_per_block = threads_per_block / 32.
  3. Calcular blocks/SM desde cada factor limitante:
    • Límite de registros: floor(65536 / (registers_per_thread * threads_per_block))
    • Límite de smem: floor(available_smem_per_SM / smem_per_block) -- ver Paso 6 para el acantilado
    • Límite de warps: floor(48 / warps_per_block) (GA104 max: 48 warps/SM)
    • Límite de bloques: 16 bloques/SM máximo en GA104
  4. Bloques/SM reales = min(register_limit, smem_limit, warp_limit, block_limit).
  5. Warps activos/SM = blocks_per_SM * warps_per_block.
  6. Umbral clave: 8 warps/SM es suficiente para ocultar latencia en GA104. Por debajo de 8 = problema estructural que causa comportamiento limitado por latencia.

Esperado: Tabla de ocupación que muestra blocks/SM, warps activos/SM y el factor limitante (registros, smem o warps).

En caso de fallo: Verificar cuFuncSetAttribute para memoria compartida dinámica. Verificar que los reportes de --resource-usage coincidan con la configuración de lanzamiento real. Si el conteo de registros es inesperadamente alto, probar --maxrregcount=N para limitar registros (intercambiando spills de registros por ocupación).

Paso 4: Calcular la Razón Cómputo/Carga Por Tile

Contar instrucciones de cómputo y bytes de carga por K-tile desde SASS (no código fuente):

  1. Desensamblar:
    cuobjdump -sass kernel.sm_86.cubin > kernel.sass
    
  2. Contar instrucciones de cómputo por tile (el bucle interno sobre un K-tile):
    • grep -c 'HMMA' kernel.sass -- ops FP16 Tensor Core
    • grep -c 'IMMA' kernel.sass -- ops INT8 Tensor Core
    • grep -c 'FFMA' kernel.sass -- multiplicación-suma fusionada FP32
  3. Contar cargas globales por tile:
    • grep -c 'LDG' kernel.sass -- cargas de memoria global
    • Multiplicar por bytes por carga (típicamente 16 bytes para LDG.128)
  4. Calcular razón: compute_ops / load_ops por tile.
  5. Clasificar usando el umbral de decisión cp.async (de gpu_reflections.md Insight 2):
    • Alto (>20:1): cp.async es netamente negativo; warp interleaving ya oculta la latencia DRAM. Enfocarse en cambios algorítmicos. Referencia: Flash Attention tiene 64 HMMA por tile = razón alta, cp.async medido -5%.
    • Medio (5-20:1): cp.async puede ayudar, hacer benchmark de ambas rutas.
    • Bajo (<5:1): cp.async fuertemente beneficioso; las cargas dominan y la copia asíncrona oculta la latencia. Referencia: IGEMM tiene 8 IMMA por tile = razón baja, cp.async medido +35%.

Esperado: Razón cómputo/carga con clasificación (alto/medio/bajo) y recomendación de cp.async.

En caso de fallo: Contar desde el desensamblado SASS, no desde el código fuente -- el compilador puede fusionar, eliminar o reordenar instrucciones. Asegurarse de contar instrucciones únicamente dentro del bucle interno (la iteración del K-tile), no del kernel completo.

Paso 5: Inspeccionar Instrucciones SASS

Examinar la mezcla completa de instrucciones SASS y los códigos de stall:

  1. Desensamblar (si no se hizo en el Paso 4):
    cuobjdump -sass kernel.sm_86.cubin > kernel.sass
    
  2. Contar tipos de instrucciones clave:
    grep -c 'HMMA.16816' kernel.sass      # FP16 Tensor Core
    grep -c 'IMMA.16816' kernel.sass      # INT8 Tensor Core
    grep -c 'FFMA' kernel.sass            # FP32 fused multiply-add
    grep -c 'LDGSTS' kernel.sass          # cp.async (global->shared)
    grep -c 'LDG' kernel.sass             # Global load
    grep -c 'STS' kernel.sass             # Shared store
    grep -c 'LDS' kernel.sass             # Shared load
    grep -c 'BAR.SYNC' kernel.sass        # Barrier synchronization
    grep -c 'SHFL' kernel.sass            # Warp shuffle (reductions)
    grep -c 'MUFU' kernel.sass            # Special function unit
    
  3. Verificar códigos de stall en instrucciones críticas:
    grep 'HMMA' kernel.sass | head -5     # Expect S08 minimum (hardware constraint)
    grep 'IMMA' kernel.sass | head -5     # Compiler emits S04, reducible to S02 via CuAssembler
    grep 'FFMA' kernel.sass | head -5     # Check for S04 (reducible to S01 on independent FFMAs)
    
  4. Identificar objetivos de optimización:
    • Stalls HMMA S08: mínimo de hardware en Ampere, no se puede reducir. Enfocarse en otra parte.
    • Stalls IMMA S04: el compilador es conservador. CuAssembler puede ajustar a S02 (15-20% de ganancia medida).
    • Stalls FFMA S04: si son independientes, reducibles a S01 vía CuAssembler.
    • BAR.SYNC excesivo: puede indicar sobre-sincronización entre etapas del pipeline.

Esperado: Tabla de conteo de instrucciones y resumen de códigos de stall con objetivos de optimización identificados.

En caso de fallo: Asegurar que la arquitectura de cuobjdump coincide con el objetivo de compilación del kernel (ambos deben ser sm_86). Si la salida SASS está vacía, el cubin puede estar corrupto -- recompilar.

Paso 6: Verificar el Acantilado de Smem

Determinar si el uso de memoria compartida cruza el acantilado de ocupación específico de la arquitectura:

  1. Leer smem/block desde la salida de --resource-usage (Paso 3) o cuobjdump --res-usage kernel.sm_86.cubin.
  2. Comparar con el umbral del acantilado:
    • GA104 (sm_86): 100 KB max smem/SM. Acantilado en 50 KB/block.
    • Confirmado empíricamente: 48 KB/block -> 2 blocks/SM (bueno), 56 KB/block -> 1 block/SM (regresión 2x).
  3. Si está por encima del acantilado (smem > 50 KB/block):
    • Blocks/SM cae a 1, warps activos caen a warps_per_block (típicamente 4).
    • Se espera regresión de rendimiento 2x por stalls de DRAM expuestos.
  4. Verificar el impacto del double-buffering: El double-buffering duplica el uso de smem. Si la smem actual es 30 KB, double-buffered = 60 KB, lo cual cruza el acantilado. Evaluar si el beneficio asíncrono supera la pérdida de ocupación.
  5. Registrar smem/block, blocks/SM y si el acantilado se cruza.

Esperado: Valor smem/block con conteo blocks/SM y declaración explícita de si el acantilado de 50 KB se cruza.

En caso de fallo: Si está por encima del acantilado y la ocupación es el cuello de botella, la estrategia de optimización debe cambiar: reducir el tamaño del tile para tener smem por debajo de 50 KB, o aceptar 1 block/SM y compensar con una razón cómputo/carga más alta por tile (más reuso de registros, K-tiles más largos).

Paso 7: Construir la Matriz de Decisión

Sintetizar los hallazgos de los Pasos 2-6 en una estrategia de optimización:

CondiciónEstrategia
Limitado por memoria + razón cómputo/carga baja (<5:1) + smem bajo el acantiladoSoftware pipelining con cp.async (LDGSTS). Solapar cargas globales con cómputo.
Limitado por memoria + razón cómputo/carga alta (>20:1) + 8+ warpsWarp interleaving ya oculta latencia. Enfocarse en cambios algorítmicos: implicit GEMM, split-Q, im2col.
Limitado por cómputo + pesado en FFMAAjuste de códigos de stall con CuAssembler: S04 -> S01 en FFMAs independientes.
Limitado por cómputo + pesado en HMMAS08 es mínimo de hardware, no se puede reducir. Aumentar reuso de tile (tiles M/N más grandes, K-loop más largo).
Limitado por cómputo + pesado en IMMACuAssembler: S04 -> S02 en instrucciones IMMA (el compilador es conservador).
Limitado por latencia (baja ocupación, ninguno saturado)Reducir smem o registros para obtener más blocks/SM. Subir por encima de 8 warps/SM.
Smem por encima del acantiladoReducir el tamaño del tile o reestructurar para tener smem/block bajo 50 KB (GA104).
  1. Clasificar las estrategias aplicables por ganancia esperada, usando los datos de razón cómputo/carga y ocupación.
  2. Estimar el rango de ganancia para cada estrategia basándose en cuán lejos está el kernel del techo relevante.
  3. Marcar conflictos: p. ej., cp.async duplica smem (puede cruzar el acantilado), tiles más grandes aumentan la presión de registros (puede reducir la ocupación).

Esperado: Lista clasificada de optimizaciones recomendadas con rango de ganancia predicho y conflictos potenciales.

En caso de fallo: Si no emerge un ganador claro, ejecutar micro-benchmarks aislando cada estrategia (p. ej., probar cp.async solo, probar tamaño de tile reducido solo) para medir el impacto real antes de combinar.

Paso 8: Documentar Hallazgos

Producir un reporte estructurado del cuello de botella:

  1. Línea base: tiempo del kernel, GFLOPS efectivos, ancho de banda efectivo, dimensiones del problema.
  2. Posición en el roofline: intensidad aritmética, clasificación, fracción alcanzada del pico.
  3. Ocupación: blocks/SM, warps activos/SM, factor limitante.
  4. Razón cómputo/carga: valor de la razón, clasificación (alto/medio/bajo), recomendación de cp.async.
  5. Resumen SASS: tabla de conteo de instrucciones, hallazgos de códigos de stall, objetivos de CuAssembler.
  6. Acantilado smem: smem/block, blocks/SM, estado del acantilado.
  7. Recomendación: estrategias de optimización clasificadas con estimaciones de ganancia.
## Bottleneck Analysis Report: [kernel_name]

### Baseline
- Problem: [dimensions]
- Kernel time: [X] ms
- Effective GFLOPS: [Y] | Effective BW: [Z] GB/s

### Roofline Classification
- Arithmetic intensity: [AI] FLOP/byte
- Balance point: [BP] FLOP/byte ([precision])
- Classification: **[compute|memory|latency]-bound**
- Attained fraction: [X]% of peak

### Occupancy
| Resource | Per Block | Limit/SM | Blocks/SM |
|----------|-----------|----------|-----------|
| Registers | [N]/thread | 65536 | [B] |
| Shared mem | [X] KB | 100 KB (cliff: 50 KB) | [B] |
| Warps | [W] | 48 | [B] |
| **Limiting** | | | **[min(B)]** |
- Active warps/SM: [W] ([sufficient|insufficient] for latency hiding)

### Compute/Load Ratio
- Compute ops/tile: [N] [HMMA|IMMA|FFMA]
- Load bytes/tile: [N] bytes ([N] LDG x [N] bytes)
- Ratio: [X]:1 — **[high|medium|low]**
- cp.async recommendation: [beneficial|neutral|detrimental]

### SASS Instruction Mix
| Instruction | Count | Notes |
|-------------|-------|-------|
| HMMA.16816 | [N] | Stall: S08 (hardware min) |
| IMMA.16816 | [N] | Stall: S04 (reducible to S02) |
| FFMA | [N] | Stall: S04 (reducible to S01) |
| LDG | [N] | |
| LDGSTS | [N] | cp.async |
| BAR.SYNC | [N] | |

### Smem Cliff
- Smem/block: [X] KB — [under|over] 50 KB cliff
- Blocks/SM: [B] — [no occupancy loss|occupancy halved]

### Recommended Optimizations (ranked)
1. [Strategy] — estimated [X-Y]% gain
2. [Strategy] — estimated [X-Y]% gain
3. [Strategy] — estimated [X-Y]% gain

Esperado: Reporte markdown completo consumible por un agente kernel-optimizer o desarrollador humano.

En caso de fallo: Re-ejecutar con diferentes tamaños de problema (p. ej., 1024, 2048, 4096, 8192) para confirmar que los hallazgos no son específicos del tamaño. Problemas pequeños pueden parecer limitados por latencia cuando el cuello de botella real a escala es el ancho de banda de memoria.

Validación

  • Línea base medida con eventos CUDA (no reloj de pared)
  • Clasificación en el roofline determinada (limitado por cómputo/memoria/latencia)
  • Ocupación calculada con factor limitante identificado
  • Razón cómputo/carga por tile calculada desde SASS
  • Mezcla de instrucciones SASS y códigos de stall documentados
  • Acantilado smem verificado contra el umbral de la arquitectura
  • Matriz de decisión aplicada con recomendación de estrategia
  • Hallazgos documentados en reporte estructurado

Errores Comunes

  • Multiplicación de re-lecturas: Conv2d directo lee cada peso 9x sin im2col, inflando el conteo de bytes 9x. Usar bytes únicos reales cargados desde DRAM, no instrucciones de carga totales, al calcular la intensidad aritmética.
  • Confundir el pico FP16 Tensor Core con el pico FP32: El pico FP16 TC es 174 TFLOPS, el pico FP32 FFMA es 21.7 TFLOPS -- una diferencia de 8x. Usar el pico equivocado hace la clasificación del roofline carezca de sentido.
  • Usar 64 KB como acantilado smem en lugar de 50 KB en GA104: GA104 (sm_86) tiene 100 KB max smem/SM. El acantilado está en 100/2 = 50 KB/block, no 64 KB. Esto es específico de la arquitectura; otras GPUs difieren.
  • Ignorar warp interleaving al evaluar cp.async: 8 warps con fases de cómputo largas (razón cómputo/carga alta) ya ocultan la latencia DRAM mediante el scheduling de warps. Añadir cp.async en este régimen añade presión de smem y sobrecarga de barrera sin beneficio (medido -5% en Flash Attention).
  • Contar instrucciones desde código fuente en lugar de SASS: El compilador puede fusionar operaciones, eliminar código muerto, desenrollar bucles de manera diferente o reordenar instrucciones. Siempre contar desde la salida de cuobjdump -sass.
  • No ejecutar iteraciones de calentamiento: El primer lanzamiento del kernel incluye sobrecarga de compilación JIT y efectos de caché frío. Siempre ejecutar 2-5 iteraciones de calentamiento antes de la ejecución medida.

Habilidades Relacionadas

  • pipeline-gpu-kernel -- implementar software pipelining con cp.async cuando el análisis identifica un kernel limitado por memoria con razón cómputo/carga baja
  • simulate-cpu-architecture -- análisis de arquitectura complementario para cuellos de botella del lado CPU en flujos de trabajo host-device

GitHub 저장소

pjt222/agent-almanac
경로: i18n/es/skills/analyze-kernel-bottleneck
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

연관 스킬

llamaguard

기타

LlamaGuard는 폭력 및 혐오 발언 등 6가지 안전 범주에서 LLM 입력과 출력을 조정하기 위한 Meta의 70-80억 파라미터 모델입니다. 94-95% 정확도를 제공하며 vLLM, Hugging Face 또는 Amazon SageMaker를 사용해 배포할 수 있습니다. 이 기술을 사용하여 AI 애플리케이션에 콘텐츠 필터링 및 안전 가드레일을 손쉽게 통합하세요.

스킬 보기

cost-optimization

기타

이 Claude Skill은 리소스 적정화, 태깅 전략, 지출 분석을 통해 개발자들이 클라우드 비용을 최적화할 수 있도록 지원합니다. AWS, Azure, GCP에서 클라우드 비용을 절감하고 비용 거버넌스를 구현하기 위한 프레임워크를 제공합니다. 인프라 비용을 분석하거나, 리소스를 적정화하거나, 예산 제약을 충족해야 할 때 사용하세요.

스킬 보기

quantizing-models-bitsandbytes

기타

이 스킬은 bitsandbytes를 사용하여 LLM을 8비트 또는 4비트 정밀도로 양자화하며, 최소한의 정확도 손실로 50-75%의 메모리 감소를 달성합니다. 제한된 GPU 메모리에서 더 큰 모델을 실행하거나 추론을 가속화하는 데 이상적이며, INT8, NF4, FP4와 같은 형식을 지원합니다. 이 스킬은 HuggingFace Transformers와 통합되어 QLoRA 학습 및 8비트 옵티마이저를 가능하게 합니다.

스킬 보기

dispatching-parallel-agents

기타

이 Claude Skill은 3개 이상의 독립적인 문제를 동시에 조사하고 해결하기 위해 다중 에이전트를 배치합니다. 공유 상태나 의존성 없이 해결 가능한 무관련 장애 시나리오에 맞게 설계되었습니다. 핵심 기능은 병렬 문제 해결로, 각 독립 문제 영역마다 하나의 에이전트를 할당하여 효율성을 극대화합니다.

스킬 보기