pipeline-gpu-kernel
关于
This Claude Skill transforms tiled GPU kernels to implement software pipelining (double-buffering), enabling the overlap of global memory loads with Tensor Core computations. It guides developers through restructuring the kernel prologue, loop, and epilogue, and helps select between LDG-register or cp.async methods based on compute/load ratios. The skill also includes verifying shared memory usage against occupancy limits and confirming the load/compute overlap at the SASS assembly level.
快速安装
Claude Code
推荐npx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/pipeline-gpu-kernel在 Claude Code 中复制并粘贴此命令以安装该技能
技能文档
GPU-Kernel pipelinen
Software-Pipelining (Double-Buffering) auf einen tiled GPU-Kernel anwenden damit globale Speicher-Loads fuer Tile N+1 mit Tensor-Core-Berechnung auf Tile N ueberlappen. Eine sequenzielle Load-Sync-Compute-Sync-K-Schleife in eine Prolog-/Schleife-/Epilog-Struktur transformieren, zwischen LDG-Register- und cp.async-(LDGSTS)-Varianten basierend auf Compute-Load-Ratio waehlen, verifizieren dass Shared Memory unter dem Architektur-Occupancy-Cliff bleibt und Load-/Compute-Ueberlappung im finalen SASS bestaetigen.
Wann verwenden
- Wenn
analyze-kernel-bottleneckeinen speicherbegrenzten Kernel mit niedriger Compute-Load-Ratio pro Tile identifiziert - Wenn Warp-Interleaving allein DRAM-Latenz nicht verstecken kann (~300 Zyklen auf GA104)
- Wenn der Kernel eine sequenzielle Load-Sync-Compute-Sync-K-Schleife hat die restrukturiert werden kann
- Nicht noetig wenn Compute-Load-Ratio hoch (>20:1) und 8+ Warps aktiv sind
Eingaben
- Erforderlich: CUDA-Kernel-Quelldatei (
.cu) mit einer tiled K-Schleife die separate Load- und Compute-Phasen enthaelt - Erforderlich: Ziel-GPU-Architektur (z.B. GA104 / sm_86 — bestimmt smem-Cliff und Occupancy-Limits)
- Erforderlich: Aktuelle Tile-Groessen (BM, BN, BK) und Datentyp (FP16, FP32, INT8)
- Optional: Compute-Load-Ratio pro Tile (aus
analyze-kernel-bottleneck; wird geschaetzt wenn nicht bereitgestellt) - Optional: Benchmark-Baseline (nicht-pipelined Performance bei Ziel-Problemgroesse)
Vorgehensweise
Schritt 1: Voraussetzungen verifizieren
Bestaetigen dass der Kernel eine tiled K-Schleife mit distinkten Load- und Compute-Phasen separiert durch __syncthreads() hat. Die verdoppelten Shared-Memory-Kosten berechnen und verifizieren dass sie unter dem Architektur-Occupancy-Cliff bleiben.
- Die K-Schleife im Kernel lokalisieren. Sie muss diese sequenzielle Struktur haben: A- und B-Tiles aus Global zu Shared-Memory laden,
__syncthreads(), Berechnung (HMMA/IMMA/FFMA) auf den Shared-Memory-Tiles,__syncthreads(). - Die Single-Buffer-Shared-Memory-Groessen aufzeichnen:
smem_a_size = BM * BK * sizeof(T)undsmem_b_size = BK * BN * sizeof(T). - Die Double-Buffer-Kosten berechnen:
smem_doubled = smem_a_size * 2 + smem_b_size * 2. - Mit dem Architektur-Cliff vergleichen. GA104 (sm_86): 100 KB max smem/SM, Cliff bei 50 KB/Block (ueber 50 KB = 1 Block/SM = 4 Warps, 2x Occupancy-Kollaps).
Single buffer: smem_a[BM*BK] + smem_b[BK*BN] = 2 KB + 2 KB = 4 KB
Double buffer: smem_a[2][BM*BK] + smem_b[2][BK*BN] = 4 KB + 4 KB = 8 KB
8 KB << 50 KB cliff -> 2 blocks/SM -> 8 warps
- Die Schleifen-Iterations-Anzahl verifizieren:
num_tiles = K / BK. Pipelining erfordertnum_tiles >= 2(mindestens ein Prolog + eine Hauptschleifen-Iteration).
Erwartet: Eine Shared-Memory-Budget-Tabelle die Single-Buffer- und Double-Buffer-Kosten zeigt und bestaetigt dass die verdoppelte Allokation unter dem Architektur-Cliff mit mindestens 2 Bloecken/SM Occupancy bleibt.
Bei Fehler: Wenn Double-Buffer den Cliff ueberschreitet, Tile-Groesse reduzieren (BK oder BM halbieren) bis smem_doubled <= 50 KB fuer GA104. Alternativ Register-only Prefetch (LDG-Variante) ohne Verdoppelung von Shared Memory nutzen — vorgefetchte Daten in Registern speichern und nach __syncthreads() in denselben Single-Buffer schreiben.
Schritt 2: Variante waehlen
Zwischen LDG-Register und cp.async (LDGSTS) basierend auf der Compute-Load-Ratio pro Tile auswaehlen.
- Die Compute-Load-Ratio berechnen:
ratio = (2 * BM * BN * BK) / ((BM * BK + BK * BN) * sizeof(T))fuer GEMM-aehnliche Kernels (2 FLOPs pro Multiply-Add, geladene Bytes pro Tile). - Die Entscheidungsregel anwenden:
LDG-Register-Variante (ratio >= 5 oder CUDA < 11.0):
- Tile N+1 mit LDG in Register laden (nicht-blockierende globale Loads).
- Auf
buf[N % 2]berechnen (ueberlappt mit ausstehenden LDGs). __syncthreads(), dann STS Register inbuf[(N+1) % 2],__syncthreads().- Einfachere Implementation, keine Pipeline-API-Abhaengigkeit.
- Fuegt Register-Druck hinzu: ~
(BM * BK + BK * BN) / BLOCK_SIZERegister pro Thread fuer Staging.
cp.async (LDGSTS) Variante (ratio < 5, CUDA >= 11.0):
__pipeline_memcpy_asyncTile N+1 direkt zubuf[(N+1) % 2](async, umgeht das Register-File).__pipeline_commit()vor Berechnung.- Auf
buf[N % 2]berechnen. __pipeline_wait_prior(0)+__syncthreads()nach Berechnung.- Bessere Ueberlappung, null Register-Druck fuer Prefetch. Erfordert
#include <cuda_pipeline.h>.
- Entscheidungs-Schwellwerte (gemessen auf GA104 mit IGEMM bei 4096x4096x4096):
- Ratio < 5:1 — cp.async bevorzugen (+35% gemessen auf IGEMM).
- Ratio 5-20:1 — beide implementieren und benchmarken um zu entscheiden.
- Ratio > 20:1 — Pipelining wahrscheinlich nicht vorteilhaft (Warp-Interleaving ausreichend).
Erwartet: Ausgewaehlte Variante mit Begruendung basierend auf Compute-Load-Ratio und Ziel-Architektur.
Bei Fehler: Wenn die Ratio mehrdeutig ist (5-20:1-Bereich), beide Varianten implementieren und benchmarken. Die cp.async-Variante ist der sicherere Default wenn die CUDA-Version sie unterstuetzt.
Schritt 3: Die K-Schleife restrukturieren
Die sequenzielle Load-Sync-Compute-Sync-Schleife in eine pipelined Prolog-/Schleife-/Epilog-Struktur transformieren.
-
Die drei Abschnitte identifizieren: Der originale Schleifen-Body wird drei Stuecke:
- Prolog: Tile 0 in
buf[0]laden, synchronisieren, dann in die Hauptschleife eintreten. - Hauptschleife: Fuer Tiles 1 bis
num_tiles - 1Laden von Tile N+1 mit Berechnung von Tile N ueberlappen. - Epilog: Das letzte Tile berechnen (bereits durch die finale Hauptschleifen-Iteration geladen).
- Prolog: Tile 0 in
-
LDG-Register-Variantenstruktur:
// === LDG-register variant ===
// Prologue: load tile 0 into buf[0]
cooperative_load_tile(smem_a[0], smem_b[0], global_a, global_b, /*k_offset=*/0);
__syncthreads();
for (int tile = 0; tile < num_tiles - 1; tile++) {
int cur_buf = tile & 1;
int next_buf = 1 - cur_buf;
// Phase 1: LDG next tile into registers (non-blocking)
float reg_a[ELEMS_PER_THREAD_A], reg_b[ELEMS_PER_THREAD_B];
prefetch_tile_to_registers(reg_a, reg_b, global_a, global_b,
(tile + 1) * BK);
// Phase 2: Compute on current buffer (overlaps with LDG flight)
tensor_core_mma(smem_a[cur_buf], smem_b[cur_buf], acc);
// Phase 3: Drain registers into next buffer
__syncthreads();
store_registers_to_smem(smem_a[next_buf], smem_b[next_buf],
reg_a, reg_b);
__syncthreads();
}
// Epilogue: compute last tile
tensor_core_mma(smem_a[(num_tiles - 1) & 1], smem_b[(num_tiles - 1) & 1], acc);
- cp.async-Variantenstruktur:
// === cp.async variant ===
#include <cuda_pipeline.h>
// Prologue: async load tile 0 into buf[0]
cpasync_load_tile(smem_a[0], smem_b[0], global_a, global_b, /*k_offset=*/0);
__pipeline_commit();
__pipeline_wait_prior(0);
__syncthreads();
for (int tile = 0; tile < num_tiles - 1; tile++) {
int cur_buf = tile & 1;
int next_buf = 1 - cur_buf;
// Phase 1: cp.async next tile into next buffer (async, direct to smem)
cpasync_load_tile(smem_a[next_buf], smem_b[next_buf],
global_a, global_b, (tile + 1) * BK);
__pipeline_commit();
// Phase 2: Compute on current buffer (overlaps with LDGSTS in flight)
tensor_core_mma(smem_a[cur_buf], smem_b[cur_buf], acc);
// Phase 3: Wait for async copies to complete
__pipeline_wait_prior(0);
__syncthreads();
}
// Epilogue: compute last tile
tensor_core_mma(smem_a[(num_tiles - 1) & 1], smem_b[(num_tiles - 1) & 1], acc);
- Den Schleifen-Count verifizieren: die Hauptschleife laeuft
num_tiles - 1Iterationen (Tiles 0 bisnum_tiles - 2indizieren welche Tiles zu berechnen, ladet Tiles 1 bisnum_tiles - 1). Der Epilog berechnet das in der letzten Iteration geladene Tile.
Erwartet: Restrukturierter K-Schleifen-Quellcode mit klaren Prolog-, Hauptschleifen- und Epilog-Abschnitten fuer die gewaehlte Variante.
Bei Fehler: Der haeufigste Bug ist ein Off-by-One in Buffer-Indexierung oder Vergessen des Epilog-Compute-Pass. Verifizieren: Prolog laedt in buf[0], erste Hauptschleifen-Iteration berechnet buf[0] und laedt in buf[1], zweite Iteration berechnet buf[1] und laedt in buf[0] und so weiter. Der Epilog berechnet buf[(num_tiles - 1) & 1].
Schritt 4: Double-Buffer implementieren
Den double-buffered Shared Memory deklarieren und die Load-Funktionen implementieren.
- Single-Buffer-Shared-Memory-Deklarationen mit double-buffered Arrays ersetzen:
// Before (single buffer)
__shared__ half smem_a[BM * BK];
__shared__ half smem_b[BK * BN];
// After (double buffer)
__shared__ half smem_a[2][BM * BK];
__shared__ half smem_b[2][BK * BN];
- Fuer die cp.async-Variante die Async-Load-Funktion mit der Pipeline-API implementieren:
__device__ void cpasync_load_tile(half* dst_a, half* dst_b,
const half* src_a, const half* src_b,
int k_offset) {
// Each thread copies its portion (16 bytes = 8 half values per cp.async)
int tid = threadIdx.x;
int bytes_per_thread = 16; // cp.async.cg supports 4, 8, or 16 bytes
// A tile: BM * BK elements, distributed across BLOCK_SIZE threads
int elems_a = BM * BK / BLOCK_SIZE;
for (int i = 0; i < elems_a; i += 8) {
int idx = tid * elems_a + i;
__pipeline_memcpy_async(dst_a + idx,
src_a + k_offset * BM + idx,
bytes_per_thread);
}
// B tile: BK * BN elements, distributed similarly
int elems_b = BK * BN / BLOCK_SIZE;
for (int i = 0; i < elems_b; i += 8) {
int idx = tid * elems_b + i;
__pipeline_memcpy_async(dst_b + idx,
src_b + k_offset * BN + idx,
bytes_per_thread);
}
}
- Fuer die LDG-Variante Register-Staging-Arrays und Store-Funktionen implementieren:
// Declare register staging (size = elements per thread)
half reg_a[BM * BK / BLOCK_SIZE];
half reg_b[BK * BN / BLOCK_SIZE];
// Prefetch: LDG from global to registers (non-blocking, issued early)
for (int i = 0; i < BM * BK / BLOCK_SIZE; i++) {
int idx = threadIdx.x * (BM * BK / BLOCK_SIZE) + i;
reg_a[i] = global_a[k_offset * BM + idx];
}
// ... similarly for reg_b
// Store: STS from registers to shared memory (after __syncthreads)
for (int i = 0; i < BM * BK / BLOCK_SIZE; i++) {
int idx = threadIdx.x * (BM * BK / BLOCK_SIZE) + i;
smem_a[next_buf][idx] = reg_a[i];
}
__launch_bounds__(BLOCK_SIZE)auf dem Kernel halten um dem Compiler akkurate Occupancy-Information zu geben.- Kompilieren:
nvcc --cubin -arch=sm_86 -O2 -o kernel.sm_86.cubin kernel.cu.
Erwartet: Kompilierbarer Kernel mit double-buffered Shared Memory und dem gewaehlten Lade-Mechanismus. Erfolgreiche cubin-Generierung ohne Fehler.
Bei Fehler: Wenn Kompilierung an Pipeline-API-Calls scheitert, sicherstellen dass #include <cuda_pipeline.h> praesent ist und CUDA-Toolkit >= 11.0. Wenn Register-Spills auftreten (mit nvcc --resource-usage pruefen), die Register-Staging-Array-Groessen reduzieren indem BLOCK_SIZE erhoeht oder BK reduziert wird.
Schritt 5: Korrektheit verifizieren
Den pipelinedKernel gegen die CPU-Referenz ausfuehren um identische numerische Ausgabe zu bestaetigen.
- Den Benchmark kompilieren:
nvcc -arch=sm_86 -O2 -o bench bench.cu -lcuda -I../../phase2/common. - Bei einer kleinen Problemgroesse zuerst ausfuehren (512x512x512) um Indexierungs-Bugs vor dem Hochskalieren abzufangen.
- Die korrekte Toleranz fuer den Datentyp anwenden:
- INT8 Tensor Core (IMMA):
abs=0.5, rel=0.1 - FP16 Tensor Core (HMMA):
abs=1e-2, rel=1e-2 - FP32 Skalar (FFMA):
abs=1e-3, rel=1e-3
- INT8 Tensor Core (IMMA):
- Pipelining aendert die Arithmetik nicht — es ordnet nur Loads neu. Wenn Korrektheit scheitert, ist der Bug in Buffer-Indexierung, nicht in der Compute-Logik.
- Bei der Ziel-Problemgroesse testen (z.B. 4096x4096x4096) um Boundary-Handhabung zu verifizieren.
Erwartet: PASS bei beiden kleinen und Ziel-Problemgroessen mit Fehlergrenzen identisch zur nicht-pipelined Baseline.
Bei Fehler: Buffer-Indexierungs-Bug ist die wahrscheinlichste Ursache. Verifizieren: Compute liest aus buf[tile & 1] waehrend Loads in buf[1 - (tile & 1)] schreiben. Pruefen dass der Epilog Buffer-Index (num_tiles - 1) & 1 verarbeitet, nicht num_tiles & 1. Fuer cp.async verifizieren dass __pipeline_wait_prior(0) vor __syncthreads() abschliesst — sonst kann Compute teilweise-geschriebene Daten lesen.
Schritt 6: Benchmarken und vergleichen
Den pipelined Kernel gegen die nicht-pipelined Baseline bei der Ziel-Problemgroesse messen.
- Die nicht-pipelined Baseline ausfuehren und GFLOPS oder Bandbreite aufzeichnen (abhaengig vom Kernel-Typ).
- Jede pipelined Variante ausfuehren und dieselbe Metrik aufzeichnen.
- Speedup berechnen:
speedup = pipelined_metric / baseline_metric. - Erwartete Gewinne nach Compute-Load-Ratio (gemessen auf GA104):
- Niedrige Ratio (<5:1): +15-35% von cp.async (IGEMM gemessen: LDG +18%, cp.async +35% bei 4096x4096x4096).
- Mittlere Ratio (5-20:1): +5-15%.
- Hohe Ratio (>20:1): 0-5% oder Regression.
- Wenn beide Varianten implementiert wurden, die schnellere fuer Production-Use auswaehlen.
| Variant | GFLOPS | Speedup vs Baseline |
|------------------|--------|---------------------|
| Baseline | XXX | 1.00x |
| LDG-register | XXX | X.XXx |
| cp.async (LDGSTS)| XXX | X.XXx |
Erwartet: Performance-Vergleichstabelle die Verbesserung zeigt. Die gewaehlte Variante sollte messbaren Speedup konsistent mit der Compute-Load-Ratio-Vorhersage zeigen.
Bei Fehler: Wenn Performance regrediert, drei Dinge pruefen: (1) SASS auf unerwarteten Instruktions-Overhead (extra BAR.SYNC, Register-Spills). (2) Shared Memory hat den Occupancy-Cliff nicht ueberschritten — mit nvcc --resource-usage oder cuobjdump -res-usage verifizieren. (3) Die Problemgroesse produziert genug Tiles (K / BK >= 4) damit Pipelining den Prolog-/Epilog-Overhead amortisieren kann.
Schritt 7: SASS-Ueberlappung verifizieren
Das kompilierte SASS inspizieren um zu bestaetigen dass globale Loads und Tensor-Core-Instruktionen innerhalb des Hauptschleifen-Body ueberlappen.
- Disassemblieren:
cuobjdump -sass kernel.sm_86.cubin | grep -E 'IMMA|HMMA|LDGSTS|LDG|BAR'. - Im Hauptschleifen-Body diese Reihenfolge verifizieren:
LDGSTS- oderLDG-Instruktionen erscheinen vorHMMA- oderIMMA-Instruktionen.- Kein
BAR.SYNCzwischen den Load-Instruktionen und den Compute-Instruktionen (sie muessen frei sein im Warp-Scheduler zu ueberlappen). BAR.SYNCerscheint nach dem Compute-Block, sperrt die Nutzung der geladenen Daten der naechsten Iteration.
- Stall-Codes auf HMMA-/IMMA-Instruktionen pruefen — S08 fuer HMMA-Pipeline-Delay ist erwartet und unvermeidbar. S01-S04 fuer IMMA ist normal. Stalls auf LDG-/LDGSTS sollten niedrig sein (S01) da der Warp-Scheduler zu Compute wechseln kann waehrend Loads in Flight sind.
- Total HMMA-/IMMA-Instruktionen pro Schleifen-Iteration zaehlen — dies sollte mit der nicht-pipelined Version uebereinstimmen (Pipelining sollte Compute-Volumen nicht aendern).
# Full SASS pipeline verification
cuobjdump -sass kernel.sm_86.cubin | grep -E 'IMMA|HMMA|LDGSTS|LDG|BAR'
# Count compute instructions per loop
cuobjdump -sass kernel.sm_86.cubin | grep -c 'HMMA\|IMMA'
# Check for register spills
nvcc --resource-usage --cubin -arch=sm_86 -O2 kernel.cu 2>&1 | grep -i spill
Erwartet: Annotierter SASS-Auszug der das Load-vor-Compute-Muster ohne dazwischenliegende Barriers zeigt. Null Register-Spills.
Bei Fehler: Wenn der Compiler Loads nach Compute reordnet (was die Ueberlappung besiegt), versuchen: (1) #pragma unroll 1 auf der Hauptschleife um zu aggressives Unrolling zu verhindern. (2) Load und Compute in distinkte Inline-Funktionen separieren um einen Sequenzierungs-Hint zu schaffen. (3) asm volatile("" ::: "memory") als Compiler-Fence zwischen Load- und Compute-Bloecken nutzen (letzter Ausweg — kann andere Optimierungen hemmen).
Validierung
- Double-Buffer smem bleibt unter Architektur-Cliff (GA104: 50 KB/Block)
- Beide Buffer alternierend verwendet (
buf[tile & 1]-Muster) - Prolog laedt Tile 0 in
buf[0] - Epilog berechnet letztes Tile aus
buf[(num_tiles - 1) & 1] - Korrektheit PASS gegen CPU-Referenz bei beiden kleinen und Ziel-Groessen
- SASS bestaetigt Load-/Compute-Ueberlappung (kein
BAR.SYNCzwischen LDGSTS/LDG und IMMA/HMMA) - Performance verbessert ueber nicht-pipelined Baseline
- Kein Register-Spill aus LDG-Variante (mit
nvcc --resource-usagepruefen)
Haeufige Stolperfallen
- Den smem-Cliff durch Verdoppelung von Buffern ueberschreiten — GA104-Cliff ist 50 KB/Block, nicht 64 KB. Immer
smem_doubledvor Implementation berechnen. Ein Kernel der 28 KB single-buffered nutzt springt auf 56 KB doubled, ueberschreitet den Cliff und halbiert Occupancy. Dies kann einen +20%-Pipelining-Gewinn in eine -50%-Occupancy-Regression verwandeln. - Den Epilog-Compute-Pass vergessen — Das letzte in der finalen Hauptschleifen-Iteration geladene Tile braucht seine eigene Compute-Phase ausserhalb der Schleife. Ohne sie werden die letzten BK-Spalten der K-Dimension still fallen gelassen, was inkorrekte Ergebnisse produziert die als kleine numerische Fehler statt offensichtlichen Versagen erscheinen koennen.
- Buffer-Indexierungs-Off-by-One —
buf[tile & 1]fuer den aktuellen Compute-Buffer undbuf[1 - (tile & 1)]fuer den naechsten Load-Buffer nutzen. Ein haeufiger Fehler ist die Nutzung vonbuf[(tile + 1) & 1]fuer den naechsten Buffer, was nur dann aequivalent zubuf[1 - (tile & 1)]ist wenn die Buffer-Anzahl 2 ist — aber falsch liest wenn versehentlich auf den Compute-Index angewendet. - cp.async-Commit-/Wait-Reihenfolge —
__pipeline_commit()muss VOR der Compute-Phase aufgerufen werden (es siegelt den Batch von Async-Kopien).__pipeline_wait_prior(0)muss NACH der Compute-Phase aufgerufen werden (es blockiert bis alle commiteten Kopien abschliessen). Diese zu vertauschen macht die Async-Kopien synchron und eliminiert allen Ueberlappungs-Vorteil. - Fehlende __syncthreads — In der LDG-Variante wird ein
__syncthreads()zwischen Compute und dem STS-Drain benoetigt (damit Compute das Lesen des aktuellen Buffers beendet bevor er ueberschrieben wird). Ein weiteres__syncthreads()wird nach dem STS-Drain benoetigt (damit alle Threads das Schreiben beenden bevor die naechste Iteration liest). In der cp.async-Variante stellt__syncthreads()nach__pipeline_wait_prior(0)sicher dass alle Threads die abgeschlossenen Async-Kopien sehen. - Boundary-Handhabung in cp.async —
__pipeline_memcpy_asyncerfordert dass die Quelladresse gueltig und ausgerichtet ist. An Matrix-Raendern woKkein Vielfaches vonBKist, kann das letzte Tile out-of-bounds lesen. Auf Skalar-Loads mit Bounds-Pruefung fuer das finale Tile zurueckfallen oder die Eingabe-Matrizen auf ein Vielfaches von BK paddern.
Verwandte Skills
analyze-kernel-bottleneck— identifizieren ob der Kernel speicherbegrenzt ist und die Compute-Load-Ratio berechnen die die Variantenauswahl treibt
GitHub 仓库
相关推荐技能
llamaguard
其他LlamaGuard是Meta推出的7-8B参数内容审核模型,专门用于过滤LLM的输入和输出内容。它能检测六大安全风险类别(暴力/仇恨、性内容、武器、违禁品、自残、犯罪计划),准确率达94-95%。开发者可通过HuggingFace、vLLM或Sagemaker快速部署,并能与NeMo Guardrails集成实现自动化安全防护。
cost-optimization
其他这个Claude Skill帮助开发者优化云成本,通过资源调整、标记策略和预留实例来降低AWS、Azure和GCP的开支。它适用于减少云支出、分析基础设施成本或实施成本治理策略的场景。关键功能包括提供成本可视化、资源规模调整指导和定价模型优化建议。
quantizing-models-bitsandbytes
其他这个Skill使用bitsandbytes库量化大语言模型,能在GPU内存有限时通过8位或4位量化减少50-75%内存占用,同时保持精度损失最小。它支持INT8、NF4、FP4等多种量化格式,可与HuggingFace Transformers无缝集成,适用于需要部署更大模型或加速推理的场景。还提供QLoRA训练和8位优化器支持,让开发者能轻松实现高效模型压缩。
dispatching-parallel-agents
其他该Skill用于并行处理3个以上无依赖关系的独立故障,可为每个问题域分派专属Claude代理同时执行调查修复。它通过并发处理多个独立问题显著提升故障排查效率,特别适用于测试文件、子系统等无共享状态的场景。
