Benchmark AI Inference Performance Before Buying Hardware
This guide walks you through benchmarking AI inference performance before you commit to specific hardware. You’ll learn how to design representative tests, measure latency and throughput, and interpret results so your hardware choice matches your real workload—not just marketing specs.
What You’ll Need
- A representative model (or a few) that you plan to deploy—e.g., a fine-tuned BERT, a ResNet, or a small LLM.
- A dataset of real or realistic input samples (text, images, audio) that matches your production input sizes.
- Access to candidate hardware: cloud instances (AWS, GCP, Azure), local GPUs, CPUs, or edge devices.
- A benchmarking tool or script: options include
triton(NVIDIA),onnxruntimeperf tool,tensorflow-servingbenchmarks, or a simple custom Python script usingtime. - Basic familiarity with command line and Python.
Step-by-Step
- Define your workload profile. Write down the key characteristics: batch size (e.g., 1, 8, 32), input sequence length or image resolution, expected concurrency (number of simultaneous requests), and acceptable latency (e.g., p95 under 100 ms). This profile drives everything else.
- Select 1–3 representative models. Choose models that are similar in size and architecture to what you’ll deploy. If you’re unsure, use a common baseline like ResNet-50 for vision or BERT-base for NLP. Avoid using the largest model you can find—it may not reflect your actual usage.
- Prepare a realistic input dataset. Gather or generate inputs that match your production distribution. For example, if your NLP model sees 512-token sequences, use that. For images, use the same resolution and color channels. Store them in a format your benchmarking tool can read (e.g., numpy arrays, TFRecord, or plain files).
- Set up the hardware environment. For cloud instances, launch identical instances with the same OS, drivers, and CUDA/cuDNN versions. For local hardware, ensure all devices have the same software stack. Document the exact versions—this matters for reproducibility.
- Choose a benchmarking method. The simplest is a Python script that loads the model, warms up, and times inference over many iterations. For more realistic server-like testing, use a serving framework (e.g., NVIDIA Triton, TorchServe) and a load generator (e.g.,
heyorwrk). - Run a warm-up phase. Before measuring, run at least 10–50 inferences to allow CUDA kernels to compile and caches to fill. This prevents cold-start effects from skewing your numbers.
- Measure latency per request. Record the time for each inference (from input to output) and compute percentiles: median, p95, p99. Do this for batch size 1 first, then for your target batch size (e.g., 8 or 32).
- Measure throughput. Run a sustained load (e.g., 1000 requests) and calculate requests per second (RPS) or inferences per second. If using a serving framework, use its built-in metrics or a load generator that reports RPS.
- Repeat on each candidate hardware. Run the exact same script and dataset on each device. Keep the software stack identical; only the hardware changes. Record all results in a table.
- Analyze results against your requirements. Compare p95 latency and max throughput. If your workload is latency-sensitive (e.g., real-time chat), prioritize low p95. If it’s batch processing, prioritize throughput. Also consider cost per inference (cloud pricing) and power draw if relevant.
- Validate with a real load test. If possible, run a short simulation with your actual serving stack and traffic pattern to confirm the benchmark results hold under realistic concurrency.
Common Mistakes
- Using a single, tiny input size. Real workloads vary; test with multiple sizes (e.g., sequence lengths 128, 512, 1024) to see how performance scales.
- Ignoring warm-up. Skipping warm-up leads to inflated latency numbers that don’t reflect steady-state performance.
- Not pinning CPU frequency. On local machines, CPU frequency scaling can skew results. Use
cpupoweror BIOS settings to fix frequency during tests. - Comparing across different software versions. A newer CUDA version can change performance by 20% or more. Always use the same versions.
- Only measuring average latency. Average hides outliers. Always report p95/p99.
- Forgetting to test batch size. Many accelerators perform much better with larger batches, but your application may not support batching. Test both.
Tips
- Use a benchmarking framework. Tools like
triton’sperf_analyzeroronnxruntime’sperftool automate many steps and provide consistent metrics. - Run multiple trials. At least 3 runs per configuration, and take the median of the medians to reduce noise.
- Monitor GPU utilization. Use
nvidia-smiornvtopto see if the GPU is actually busy. If utilization is low, your bottleneck may be CPU or data loading, not the accelerator. - Check memory usage. Ensure your model fits in VRAM/RAM with headroom for activations. Out-of-memory errors will crash your benchmark.
- Document everything. Save the exact command, model file, input shapes, and software versions. This lets you reproduce and compare later.
Troubleshooting
- Benchmark crashes or gives wildly inconsistent results. Check for thermal throttling (especially on laptops), background processes, or insufficient memory. Close all other applications and re-run.
- GPU utilization is low (e.g., under 50%). Your data loading or preprocessing might be the bottleneck. Pre-load all inputs into memory, or use a data loader with multiple workers.
- Latency spikes randomly. Could be due to CPU frequency scaling, network interference (if using cloud), or other tenants. Run multiple trials and look at the distribution—if spikes are rare, ignore them; if frequent, investigate.
- Results differ between runs on the same hardware. Ensure you’re using the same software stack and that the device is in a steady state. Run a longer warm-up and more iterations.
- Model fails to load on one device. Check for missing libraries or incompatible model format. Convert the model to ONNX or TensorRT if needed, but ensure the conversion is identical across devices.
Frequently Asked Questions
How many iterations should I run?
At least 100 after warm-up, but 1000 is better for stable percentiles. The more iterations, the more reliable the p99.
Should I benchmark with batch size 1 or larger?
Both. Batch size 1 is typical for online serving; larger batches (e.g., 32) are typical for offline processing. Your production use case determines which matters more.
What is a good p95 latency for AI inference?
It depends on your application. Real-time voice or interactive chat might need under 100 ms; image classification for batch jobs can tolerate seconds. Define your own threshold based on user experience.
Do I need to benchmark on every cloud provider?
Only if you’re considering multiple providers. But if you’re choosing between GPU types (e.g., A10 vs. T4), benchmark those specific instances.
Can I trust vendor-published benchmarks?
They are useful for rough comparisons but often use synthetic models or ideal conditions. Your own benchmark with your actual model is the only reliable way to decide.
How do I account for cost in my decision?
Divide the cloud instance price per hour by the throughput (requests/hour) to get cost per 1000 requests. Compare that across hardware, but also factor in latency if your workload is sensitive.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.