[mpact][profiler] Add utils for profiling Python programs and torch ops (#59)
diff --git a/benchmark/README.md b/benchmark/README.md index 4749547..e870ae9 100644 --- a/benchmark/README.md +++ b/benchmark/README.md
@@ -24,3 +24,14 @@ ```shell python path/to/the/kernels_benchmark.py --benchmark-filter=add ``` + +### Profiler + +Utils for profiling python scripts and pytorch models could be found in +`benchmark/python/utils/profiler.py`. + +To run the profiling example, use the following command: + +```shell +python benchmark/python/utils/profiler.py +```
diff --git a/benchmark/python/utils/profiler.py b/benchmark/python/utils/profiler.py new file mode 100644 index 0000000..8bca04b --- /dev/null +++ b/benchmark/python/utils/profiler.py
@@ -0,0 +1,66 @@ +import torch +import cProfile +from pstats import Stats + + +def profile_torch( + func, args, row_limit=10, save_output=False, func_name=None, file_name="trace" +): + """Use PyTorch's profiler to profile torch ops. + + To see the graph: upload trace.json to chrome://tracing + + More details about PyTorch profiler: + https://pytorch.org/tutorials/recipes/recipes/profiler_recipe.html + """ + func_name = func_name if func_name else func.__name__ + with torch.profiler.profile() as prof: + with torch.profiler.record_function(func_name): + func(*args) + print(prof.key_averages().table(sort_by="cpu_time_total", row_limit=row_limit)) + if save_output: + prof.export_chrome_trace(f"{file_name}.json") + + +def profile_python(func, args, row_limit=10, save_output=False, file_name="stats"): + """Use cProfile to profile python function calls. + + To see the graph, run the following commands: + 1. python -m pip install snakeviz + 2. snakeviz stats.prof + """ + pr = cProfile.Profile() + pr.enable() + func(*args) + pr.disable() + stats = Stats(pr) + stats.sort_stats("tottime").print_stats(row_limit) + if save_output: + pr.dump_stats(f"{file_name}.prof") + + +if __name__ == "__main__": + # Example usage of the profiler. + from mpact.models.kernels import MMNet + from mpact_benchmark.utils.tensor_generator import generate_tensor + from mpact.mpactbackend import mpact_jit + + # Generate input tensors. + dense_tensor1 = generate_tensor(seed=0, shape=(32, 32), sparsity=0.8) + dense_tensor2 = generate_tensor(seed=1, shape=(32, 32), sparsity=0.8) + sparse_tensor1 = dense_tensor1.to_sparse_csr() + sparse_tensor2 = dense_tensor2.to_sparse_csr() + + # Profile with PyTorch profiler for torch operators. + # MPACT sparse. + profile_torch(mpact_jit, (MMNet(), sparse_tensor1, sparse_tensor2)) + # Torch sparse. + profile_torch( + MMNet(), (sparse_tensor1, sparse_tensor2), func_name="sparsexsparse matmul" + ) + + # Profile with cProfile for Python function calls. + # MPACT sparse. + profile_python(mpact_jit, (MMNet(), sparse_tensor1, sparse_tensor2)) + # Torch sparse. + profile_python(MMNet(), (sparse_tensor1, sparse_tensor2))