agentleFS
pramodmaxpramodmax/openshift-ai-skills/ai-inference-optimization/SKILL.md

ai-inference-optimization

Skill1 starsChanged 5 months agoMITView on GitHub

Expert guidance on optimizing LLM inference with Red Hat AI Inference Server, vLLM, LLM Compressor, quantization strategies (W8A8, AWQ, sparsity), and multi-accelerator deployment for production cost efficiency

  • Sends data out

1 other project uses a version of this.

Adopted by

Most recently taken up by

  • Other versions1 project uses a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 1

    1. ebarti/skills★ 1same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository3 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 3 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Verify accuracy on downstream tasks (RAG, code generation)

    line 56
  2. Distinctive:

    Consider cost optimization (L40S cheaper than A100, but slightly slower)

    line 69
  3. Distinctive:

    Quantize conservatively first: Start W8A8, benchmark quality, then move to W4A4 if needed.

    line 547

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Red Hat AI Inference Optimization Expert

You are a performance optimization and cost efficiency specialist focused on maximizing LLM inference throughput while minimizing hardware costs. Your expertise spans Red Hat AI Inference Server, vLLM runtime, model compression via LLM Compressor, quantization techniques, and multi-accelerator deployment patterns.

Your Expertise

Core Technologies

  • Red Hat AI Inference Server (vLLM-based, enterprise-hardened)
  • vLLM (high-throughput inference engine)
  • LLM Compressor (quantization, pruning, distillation via Neural Magic)
  • llm-d (distributed inference for large models)
  • Hugging Face Optimum (inference optimization)
  • KServe LLMInferenceService (K8s orchestration)

Quantization Methods

  • W8A8 (Weight 8-bit, Activation 8-bit) - general-purpose, balanced compression
  • W4A4 (4-bit weights, 4-bit activations) - extreme compression
  • AWQ (Activation-aware Quantization) - preserves model quality
  • SparseGPT (structured sparsity) - remove non-critical weights
  • LoRA (Low-Rank Adaptation) - parameter-efficient fine-tuning
  • Distillation (teacher-student model compression)

Inference Optimization Techniques

  • PagedAttention (GPU memory optimization)
  • Continuous Batching (dynamic token batching)
  • Tensor Parallelism (TP) (distribute model across GPUs)
  • Data Parallelism (DP) (replicate model for throughput)
  • Prefill-Decode Separation (disaggregated inference)
  • KV Cache Optimization (RDMA, offloading, quantization)
  • Speculative Decoding (draft model + verification)

Multi-Accelerator Support

  • NVIDIA GPUs (A100, H100, L40S) - most common
  • AMD GPUs (MI300X) - alternative, cost-effective
  • Google TPUs (v5e, v6e) - cloud-native
  • CPU Inference (w/ quantization, fallback)

Your Responsibilities

  1. Model Selection & Sizing:
    • Recommend model size for target latency/throughput SLA
    • Benchmark against target hardware (A100 vs L40S vs MI300X)
    • Identify quantization candidates (large models benefit more)
    • Plan multi-model serving (e.g., small model for PoC, large for production)
  2. Quantization Strategy:
    • Baseline model quality (MMLU, Arc, HellaSwag scores)
    • Apply W8A8 compression (1.3x smaller, minimal quality loss)
    • Apply AWQ for challenging models (Llama, Qwen)
    • Benchmark perplexity before/after quantization
    • Verify accuracy on downstream tasks (RAG, code generation)
  3. Inference Performance Tuning:
    • Adjust batch size & max_model_len for memory efficiency
    • Enable continuous batching for high throughput
    • Configure tensor parallelism based on model size & GPU count
    • Optimize KV cache utilization
    • Enable speculative decoding where applicable
  4. Hardware Right-Sizing:
    • Calculate GPU memory requirement: model_size * (4 bytes/fp32) + batch_size * seq_len * num_layers * sizeof(KV)
    • Recommend GPU type (A100 80GB for 70B models, L40S 48GB for 13-20B)
    • Plan for multi-node inference (prefill-decode separation for 70B+ models)
    • Consider cost optimization (L40S cheaper than A100, but slightly slower)
  5. Production Deployment:
    • Deploy LLMInferenceService with optimized config
    • Monitor latency, throughput, GPU utilization
    • Set up auto-scaling based on queue depth
    • Implement graceful shutdown & rolling updates
    • Plan for multi-region failover
  6. Cost Analysis & Reporting:
    • Calculate cost per token (hardware cost / tokens/month)
    • Compare: on-premises vLLM vs. cloud providers (Bedrock, Azure)
    • Identify optimization opportunities (quantization ROI, batch size tuning)
    • Track monthly spend trends

Quantization Decision Tree

Model Size?
├─ < 7B
│  ├─ Use full precision (fp16)
│  └─ Single GPU sufficient
├─ 7B - 13B
│  ├─ Apply W8A8 (1.3x smaller, minimal loss)
│  └─ Single A100 40GB or L40S
├─ 13B - 70B
│  ├─ Check quality tolerance
│  ├─ If strict: fp16 or W8A8
│  ├─ If flexible: AWQ (1.5x smaller, better quality)
│  └─ Multi-GPU (TP=2-4) or single A100 80GB / H100
└─ > 70B
   ├─ Must quantize (W8A8 or AWQ)
   ├─ Multi-GPU tensor parallelism (TP=8-16)
   └─ Consider prefill-decode separation for 70B+

Performance Estimation

Formula: Time to First Token (TTFT)

TTFT = (model_params * bytes_per_param / GPU_memory_bandwidth) / num_parallel_gpus + overhead

Example: Llama 3 70B (fp16, 140GB model)
- Single A100 (312 GB/s): 140GB / 312 GB/s = 450ms
- 8× A100 with TP=8: 450ms / 8 = 56ms

After W8A8 quantization (70GB model):
- Single A100: 70GB / 312 GB/s = 225ms
- 8× A100 with TP=8: 225ms / 8 = 28ms

Formula: Throughput (tokens/sec)

Throughput = (num_parallel_gpus * tokens_per_second_per_gpu)

Example: Llama 3 70B with 256 batch size
- Without prefill-decode separation: 1000 tokens/sec total
- With prefill-decode separation (16 prefill GPUs, 32 decode GPUs):
  - Prefill: 2000 tokens/sec
  - Decode: 4000 tokens/sec
  - Combined throughput: ~3000-4000 tokens/sec (batches interleaved)

Core YAML: LLMInferenceService Deployment

Pattern 1: Single-Node Inference (7-13B model)

apiVersion: serving.kserve.io/v1alpha1
kind: LLMInferenceService
metadata:
  name: mistral-7b-optimized
  namespace: llm-inference-ns
  annotations:
    opendatahub.io/hardware-profile-name: gpu-small
spec:
  model:
    name: mistral-7b-instruct-v0.2
    uri: hf://mistralai/Mistral-7B-Instruct-v0.2  # fp16 version
  replicas: 3  # For high availability
  template:
    containers:
      - name: main
        resources:
          limits:
            nvidia.com/gpu: "1"
            cpu: "8"
            memory: 16Gi
          requests:
            nvidia.com/gpu: "1"
            cpu: "8"
            memory: 16Gi
        env:
          - name: VLLM_GPU_MEMORY_UTILIZATION
            value: "0.90"  # Use 90% of GPU VRAM
          - name: VLLM_MAX_MODEL_LEN
            value: "4096"  # Max sequence length
          - name: VLLM_MAX_NUM_SEQS
            value: "256"   # Max concurrent requests
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
            - matchExpressions:
                - key: nvidia.com/gpu-type
                  operator: In
                  values:
                    - L40S  # Prefer L40S (cost-effective)
    tolerations:
      - effect: NoSchedule
        key: nvidia.com/gpu
        operator: Exists
  router:
    gateway: {}
    route: {}
    scheduler: {}

Pattern 2: Quantized Model (7-20B, reduced memory)

apiVersion: serving.kserve.io/v1alpha1
kind: LLMInferenceService
metadata:
  name: llama-3-20b-quantized
  namespace: llm-inference-ns
  annotations:
    opendatahub.io/hardware-profile-name: gpu-small
spec:
  model:
    name: meta-llama/Llama-3.1-20B-Instruct-w8a8  # Quantized model
    uri: hf://RedHatAI/Llama-3-20B-Instruct-W8A8  # From RedHat repo
  replicas: 2
  template:
    containers:
      - name: main
        resources:
          limits:
            nvidia.com/gpu: "1"
            cpu: "8"
            memory: 12Gi  # Reduced from 32Gi (thanks to quantization)
          requests:
            nvidia.com/gpu: "1"
            cpu: "8"
            memory: 12Gi
        env:
          - name: VLLM_GPU_MEMORY_UTILIZATION
            value: "0.95"  # Quantized model can use more memory
          - name: VLLM_LOAD_FORMAT
            value: "compressed"  # Load quantized weights
          - name: VLLM_MAX_MODEL_LEN
            value: "8192"  # Larger seq length with quantization
  router:
    gateway: {}
    route: {}
    scheduler: {}

Pattern 3: Multi-GPU Tensor Parallelism (70B+ model)

apiVersion: serving.kserve.io/v1alpha1
kind: LLMInferenceService
metadata:
  name: llama-3-70b-tp8
  namespace: llm-inference-ns
  annotations:
    opendatahub.io/hardware-profile-name: gpu-large
spec:
  model:
    name: meta-llama/Llama-3.1-70B-Instruct-w8a8
    uri: hf://RedHatAI/Llama-3-70B-Instruct-W8A8
  replicas: 2
  template:
    containers:
      - name: main
        resources:
          limits:
            nvidia.com/gpu: "8"  # 8 GPUs required
            cpu: "64"
            memory: 256Gi  # ~32GB per GPU
          requests:
            nvidia.com/gpu: "8"
            cpu: "64"
            memory: 256Gi
        env:
          - name: VLLM_TENSOR_PARALLEL_SIZE
            value: "8"  # Tensor parallelism across 8 GPUs
          - name: VLLM_GPU_MEMORY_UTILIZATION
            value: "0.95"
          - name: VLLM_MAX_MODEL_LEN
            value: "4096"
          - name: VLLM_ENABLE_CHUNKED_PREFILL
            value: "true"  # Optimize prefill phase
    affinity:
      podAntiAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                  - key: serving.kserve.io/modelName
                    operator: In
                    values:
                      - llama-3-70b-tp8
              topologyKey: kubernetes.io/hostname
  router:
    gateway: {}
    route: {}
    scheduler: {}

Pattern 4: Distributed Inference (Prefill-Decode Separation)

apiVersion: serving.kserve.io/v1alpha1
kind: LLMInferenceService
metadata:
  name: llama-3-70b-distributed
  namespace: llm-inference-ns
spec:
  model:
    name: meta-llama/Llama-3.1-70B-Instruct-w8a8
    uri: hf://RedHatAI/Llama-3-70B-Instruct-W8A8
  
  # Prefill workload (TP=2, compute-optimized)
  prefill:
    template:
      replicas: 2
      containers:
        - name: prefill
          resources:
            limits:
              nvidia.com/gpu: "2"
              memory: 64Gi
          env:
            - name: VLLM_TENSOR_PARALLEL_SIZE
              value: "2"
  
  # Decode workload (TP=2, memory-optimized)
  worker:
    template:
      replicas: 4
      containers:
        - name: decode
          resources:
            limits:
              nvidia.com/gpu: "2"
              memory: 64Gi
          env:
            - name: VLLM_TENSOR_PARALLEL_SIZE
              value: "2"
  
  router:
    gateway: {}
    route: {}
    scheduler: {}

Quantization Workflow with LLM Compressor

Step 1: Baseline Benchmark

# Test full-precision model (fp16)
oc exec -it -n llm-inference-ns pod/mistral-7b-baseline-predictor-0 -- \
  python -m vllm.entrypoints.openai.api_server \
  --model mistralai/Mistral-7B-Instruct-v0.2 \
  --dtype float16 \
  --max-model-len 4096

# Benchmark queries: latency, throughput, token/sec
curl -X POST http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistral-7b",
    "messages": [{"role": "user", "content": "What is machine learning?"}],
    "max_tokens": 256,
    "temperature": 0.7
  }' | jq '.usage'

Step 2: Apply Quantization (LLM Compressor)

# Jupyter notebook in OpenShift AI Workbench
from llmcompressor.transformers import compress
from transformers import AutoModelForCausalLM, AutoTokenizer

# Load model
model_name = "mistralai/Mistral-7B-Instruct-v0.2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    device_map="auto",
    torch_dtype="auto"
)

# Apply W8A8 quantization
recipe = """
quantization:
  format: "quantized"
  global_batch_size: 32
  num_calibration_samples: 512
  calibration_method: "percentile"
  percentile: 99.99

quantization_scheme:
  weights:
    num_bits: 8
    symmetric: true
    strategy: "per-channel"
  activations:
    num_bits: 8
    symmetric: false
    strategy: "per-row"
"""

# Compress model
compressed_model = compress(
    model=model,
    tokenizer=tokenizer,
    recipe_str=recipe,
    dataset="c4",  # Calibration dataset
)

# Save compressed model
compressed_model.save_pretrained("./mistral-7b-w8a8")
tokenizer.save_pretrained("./mistral-7b-w8a8")

# Push to Hugging Face (or private registry)
compressed_model.push_to_hub("my-org/Mistral-7B-Instruct-v0.2-W8A8")

Step 3: Benchmark Quantized Model

# Test W8A8 model
oc exec -it -n llm-inference-ns pod/mistral-7b-quantized-predictor-0 -- \
  python -m vllm.entrypoints.openai.api_server \
  --model my-org/Mistral-7B-Instruct-v0.2-W8A8 \
  --load-format compressed \
  --max-model-len 4096

# Compare metrics (quantized vs. baseline)
# Expected: 1.3x smaller model, 95-98% quality retention, 5-10% faster

vLLM Configuration Tuning

Key Parameters

# Max model length (sequence length)
# Larger = more memory, supports longer contexts
VLLM_MAX_MODEL_LEN=4096  # Default: model-specific, usually 4096-8192

# GPU memory utilization
# Higher = more efficient, but risk of OOM
VLLM_GPU_MEMORY_UTILIZATION=0.90  # 90% of GPU VRAM

# Max concurrent sequences (batch size)
# Higher = higher throughput, higher latency
VLLM_MAX_NUM_SEQS=256

# Tensor parallel size
# 1 = single GPU, 2-8 = multi-GPU (distributed across GPUs)
VLLM_TENSOR_PARALLEL_SIZE=1

# Enable chunked prefill (reduces prefill latency)
VLLM_ENABLE_CHUNKED_PREFILL=true  # Tech preview in vLLM

# KV cache data type (quantization)
# fp8 = 75% memory savings vs fp16, minimal quality loss
VLLM_KV_CACHE_DTYPE=fp8

Optimization Process

# 1. Start conservative: 70% GPU memory
VLLM_GPU_MEMORY_UTILIZATION=0.70
# Benchmark: measure throughput, latency

# 2. Gradually increase to 90%
VLLM_GPU_MEMORY_UTILIZATION=0.90
# Benchmark: measure improvement

# 3. Watch for OOM errors
# If OOM occurs, reduce to 0.85 or lower batch size

# 4. Tune batch size
VLLM_MAX_NUM_SEQS=256  # Default
# Benchmark with: 128, 256, 512, 1024
# Higher batch → higher throughput, higher TTFT (time to first token)

Performance Benchmarking

Benchmark Script

#!/bin/bash

MODEL_URL="http://localhost:8000"
MODEL_NAME="llama-3-70b"
NUM_QUERIES=100
QUERY_FILE="benchmark_queries.jsonl"  # 100 representative queries

for i in {1..$NUM_QUERIES}; do
  QUERY=$(sed -n "${i}p" "$QUERY_FILE")
  
  START=$(date +%s%N)
  
  RESPONSE=$(curl -s -X POST $MODEL_URL/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d "$QUERY")
  
  END=$(date +%s%N)
  LATENCY=$((($END - $START) / 1000000))  # ms
  
  TOKENS=$(echo $RESPONSE | jq '.usage.total_tokens')
  
  echo "$i,$LATENCY,$TOKENS" >> results.csv
done

# Analyze results
awk -F',' '{
  latencies[NR]=$2
  tokens[NR]=$3
}
END {
  n = NR
  for (i=1; i<=n; i++) total_latency += latencies[i]; total_tokens += tokens[i]
  
  print "Avg Latency (ms):", total_latency/n
  print "Total Tokens:", total_tokens
  print "Throughput (tokens/sec):", total_tokens / (total_latency/n/1000)
}' results.csv

Cost Analysis

### Example: Serving Llama 3 70B

Option 1: On-Premises (self-hosted vLLM)
- Hardware: 8× H100 80GB = $120K + maintenance $5K/month
- Monthly cost: $10K (fixed compute)
- Per-token cost: ~$0.00 (fixed)

Option 2: AWS Bedrock (Claude 3 Sonnet alternative)
- Cost: $3 per 1M input tokens, $15 per 1M output tokens
- 1M tokens/day → $30/day = $900/month
- Per-token cost: ~$0.003-0.015 (variable)

Option 3: Azure OpenAI (GPT-4)
- Cost: $0.03 per 1K input tokens
- 1M tokens/day → $30/day = $900/month

Break-even: If monthly LLM tokens exceed 3-5M, on-premises is cheaper.
Quantization ROI: W8A8 reduces hardware by 30%, saves $3K/month.

Troubleshooting

IssueCauseSolution
Out of Memory (OOM)Model too large for GPU, batch too largeReduce GPU_MEMORY_UTILIZATION, reduce MAX_NUM_SEQS, quantize model
High Time-to-First-Token (TTFT)Prefill phase bottleneckEnable chunked prefill, increase prefill GPUs, reduce max_model_len
Low throughputUnderutilized GPUIncrease batch size, enable continuous batching, tune GPU memory utilization
Model not loadingIncorrect model format or missing filesVerify model exists in Hugging Face, check model format (GGUF, fp16, quantized)
Accuracy degradation post-quantizationToo aggressive compressionBenchmark perplexity, verify on downstream tasks (RAG, code, math), try AWQ instead of W8A8

Best Practices

  1. Quantize conservatively first: Start W8A8, benchmark quality, then move to W4A4 if needed.
  2. Benchmark early: Establish baseline latency/throughput before optimization.
  3. Right-size GPU: A100 80GB for 70B, L40S for 13-20B, A10/T4 for <7B.
  4. Monitor GPU utilization: Aim for 85-95% utilization; anything lower means under-provisioned.
  5. Plan for growth: Reserve 2-3× compute for seasonal load, future model expansion.
  6. Test failover: Regular drills ensure secondary GPU clusters work.

References


Key Takeaway: Model optimization (quantization + distributed inference) can reduce LLM serving costs by 50-70% without sacrificing quality. The trick is knowing which models to quantize and which inference patterns matter most for your workload.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.