Portable profiling suite for CUDA applications with roofline model visualization.
- Automated profiling of multiple CUDA executables
- GPU specifications detection and theoretical peak calculation
- Roofline model visualization (DRAM, L2, Shared memory)
- Performance metrics: execution time, occupancy, arithmetic intensity
- Flexible filtering by executables and kernels
- Multi-format output: CSV data, plots (PNG/SVG), and data files
| File | Description |
|---|---|
profile_cuda.sh |
Main profiling orchestration script |
gpu_info.cu |
GPU specification detection tool (CUDA source) |
parse_metrics.py |
Python script for parsing profiler output and generating data files |
plot_roofline.gp |
Gnuplot script for roofline model visualization |
plot_histogram.gp |
Gnuplot script for execution time histograms |
plot_occupancy.gp |
Gnuplot script for SM occupancy bar charts |
Makefile |
Build rules for gpu_info |
README.md |
This documentation file |
- CUDA Toolkit (with
nvcc) - Python 3.6+
- NVIDIA GPU with compute capability 3.0+
- Nsight Compute (
ncu) - Recommended for modern GPUs - nvprof - Legacy tool (deprecated but still functional)
- gnuplot - For automated plot generation
- Clone or copy the profiling tools to your repository:
mkdir profiling_tools
cd profiling_tools
# Copy all files here- Make scripts executable:
chmod +x profile_cuda.sh- Compile the GPU info tool:
nvcc -o gpu_info gpu_info.cuProfile all executables in a directory:
./profile_cuda.sh -d /path/to/executables
# or
./profile_cuda.sh --dir /path/to/executablesPass arguments to your executables:
./profile_cuda.sh -d ./build -a "--n 1024 --threads 256"
# or
./profile_cuda.sh --dir ./build --args "--n 1024 --threads 256"Profile only specific executables:
./profile_cuda.sh -d ./build -e "app1,app2,app3"
# or
./profile_cuda.sh --dir ./build --executables "app1,app2,app3"Profile only specific kernels:
./profile_cuda.sh -d ./build -k "matmul,reduction,scan"
# or
./profile_cuda.sh --dir ./build --kernels "matmul,reduction,scan"Specify output directory name:
./profile_cuda.sh -d ./build -o "experiment1"
# or
./profile_cuda.sh --dir ./build --output "experiment1"./profile_cuda.sh \
-d ./cuda_apps \
-e "solver_v1,solver_v2,solver_optimized" \
-k "computeFlux,updateCells" \
-a "--config config.ini --iterations 10000" \
-o "performance_study"Show all available options:
./profile_cuda.sh -h
# or
./profile_cuda.sh --helpProfiling creates a timestamped directory with all results:
your_exec_dir/
└── profiling_results_20240101_120000/
├── gpu_info.log # GPU specifications
├── roofline_specs.gp # Specs for gnuplot
├── executable1_summary.csv # Timing summary
├── executable1_compute.csv # FLOP counts
├── executable1_memory.csv # Memory transactions
├── executable1_occupancy.csv # Occupancy metrics
├── executable1.log # Execution output
├── roofline_data.dat # Roofline plot data
├── time_data.dat # Timing bar chart data
├── occupancy_data.dat # Occupancy data
├── roofline_fp64.png # Roofline plot
├── histogram_times.png # Timing comparison
└── occupancy.png # Occupancy comparison
The roofline plot shows:
- X-axis: Arithmetic Intensity (FLOP/Byte)
- Y-axis: Performance (GFLOP/s)
- Roofline lines: Memory bandwidth bounds (DRAM, L2, Shared)
- Horizontal line: Peak compute performance
- Points: Your kernels' actual performance
Interpretation:
- Points below DRAM line: Memory bound
- Points below peak line but above memory lines: Compute bound
- Closer to rooflines = better performance
Bar chart comparing total execution time across versions.
Shows SM occupancy (0-1) for each version:
- 1.0: Perfect occupancy
- 0.5: Half of available warps active
- < 0.3: Poor occupancy, may limit performance
Run standalone to get GPU specs:
./gpu_infoOutput includes:
- Architecture (Ampere, Turing, Pascal, etc.)
- CUDA cores and clock speeds
- Memory hierarchy specifications
- Theoretical peak bandwidths and FLOP/s
Select specific GPU:
./gpu_info 1 # Use GPU device 1Edit profile_cuda.sh to add/remove nvprof/ncu metrics:
# Add more compute metrics
ncu --metrics sm__inst_executed.sum,sm__cycles_active.sum ...
# Add more memory metrics
ncu --metrics l1tex__t_bytes_pipe_lsu_mem_global_op_ld.sum ...Edit plot_*.gp files to customize:
- Colors and line styles
- Axis ranges and labels
- Output formats (PNG, SVG, PDF)
Edit parse_metrics.py to:
- Change kernel name extraction logic
- Modify metric aggregation
- Add custom calculations
- Ensure your directory contains executable files
- Check file permissions (
chmod +x your_app) - Use
--executablesto specify names explicitly
- Install CUDA Toolkit completely
- Add CUDA bin directory to PATH:
export PATH=/usr/local/cuda/bin:$PATH
- Reduce number of iterations in your application
- Use
--kernelsto profile only specific kernels - Profile with smaller input datasets
- Install gnuplot:
sudo apt install gnuplot(Ubuntu) orbrew install gnuplot(macOS) - Check that
.datfiles were created - Run gnuplot manually:
gnuplot plot_roofline.gp
- Make scripts executable:
chmod +x *.sh - Check write permissions in target directory
- Reduce profiling overhead: Use reduced iteration counts for profiling runs
- Focus on hotspots: Profile only performance-critical kernels
- Compare versions: Keep consistent input sizes when comparing implementations
- Check occupancy: Low occupancy often indicates optimization opportunities
- Memory patterns: High AI suggests compute-bound, low AI suggests memory-bound
Profile multiple configurations:
for config in config1.ini config2.ini config3.ini; do
./profile_cuda.sh --dir ./build --args "$config output 1000" --output "run_$config"
doneAdd application-specific metrics to parse_metrics.py:
def calculate_custom_metric(kernels):
# Example: Calculate bandwidth utilization
actual_bw = total_bytes / total_time / 1e9
utilization = actual_bw / specs['bw_dram']
return utilization