diff --git a/CHANGELOG.md b/CHANGELOG.md index fee05bc0f3..5dd8f750e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ## Cairo-VM Changelog #### Upcoming Changes + +* feat: Create hyper_threading crate to benchmark the `cairo-vm` in a hyper-threaded environment [#1679](https://github.com/lambdaclass/cairo-vm/pull/1679) + * feat: add a `--tracer` option which hosts a web server that shows the line by line execution of cairo code along with memory registers [#1265](https://github.com/lambdaclass/cairo-vm/pull/1265) * feat: Fix error handling in `initialize_state`[#1657](https://github.com/lambdaclass/cairo-vm/pull/1657) diff --git a/Cargo.lock b/Cargo.lock index 783fb44464..c3cd2a2000 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1691,6 +1691,15 @@ dependencies = [ "want", ] +[[package]] +name = "hyper_threading" +version = "1.0.0-rc1" +dependencies = [ + "cairo-vm", + "rayon", + "tracing", +] + [[package]] name = "iai-callgrind" version = "0.3.1" @@ -2547,9 +2556,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ "either", "rayon-core", diff --git a/Cargo.toml b/Cargo.toml index 707673bde6..f3825f5efa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,8 @@ members = [ "hint_accountant", "examples/wasm-demo", "cairo1-run", - "cairo-vm-tracer" + "cairo-vm-tracer", + "examples/hyper_threading" ] default-members = [ "cairo-vm-cli", diff --git a/Makefile b/Makefile index 5467a61bbf..145b221782 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ endif compare_benchmarks_deps compare_benchmarks docs clean \ compare_trace_memory compare_trace compare_memory compare_pie compare_all_no_proof \ compare_trace_memory_proof compare_all_proof compare_trace_proof compare_memory_proof compare_air_public_input compare_air_private_input\ + hyper-threading-benchmarks \ cairo_bench_programs cairo_proof_programs cairo_test_programs cairo_1_test_contracts cairo_2_test_contracts \ cairo_trace cairo-vm_trace cairo_proof_trace cairo-vm_proof_trace \ fuzzer-deps fuzzer-run-cairo-compiled fuzzer-run-hint-diff build-cairo-lang hint-accountant \ create-proof-programs-symlinks \ @@ -375,3 +376,7 @@ hint-accountant: build-cairo-lang create-proof-programs-symlinks: cd cairo_programs/proof_programs; ln -s ../*.cairo . + +hyper-threading-benchmarks: cairo_bench_programs + cargo build -p hyper_threading --release && \ + sh examples/hyper_threading/hyper-threading.sh diff --git a/README.md b/README.md index bfa07edd4b..a213ad393e 100644 --- a/README.md +++ b/README.md @@ -295,6 +295,12 @@ Run only the `iai_benchmark` benchmark suite with cargo: cargo bench --bench iai_benchmark ``` +Benchmark the `cairo-vm` in a hyper-threaded environment with the [`examples/hyper_threading/ crate`](examples/hyper_threading/) +```bash +make hyper-threading-benchmarks +``` + + ## 📜 Changelog Keeps track of the latest changes [here](CHANGELOG.md). diff --git a/examples/hyper_threading/Cargo.toml b/examples/hyper_threading/Cargo.toml new file mode 100644 index 0000000000..e518c2bdc0 --- /dev/null +++ b/examples/hyper_threading/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "hyper_threading" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +readme.workspace = true +keywords.workspace = true + + +[dependencies] +cairo-vm = { workspace = true } +rayon = "1.9.0" +tracing = "0.1.40" diff --git a/examples/hyper_threading/README.md b/examples/hyper_threading/README.md new file mode 100644 index 0000000000..e69152ef2a --- /dev/null +++ b/examples/hyper_threading/README.md @@ -0,0 +1,11 @@ +# Hyper-Threading Benchmarks for Cairo-VM + +## Overview +This crate is designed to benchmark the performance of Cairo-VM in a hyper-threaded environment. By leveraging the [Rayon library](https://docs.rs/rayon/latest/rayon/), we can transform sequential computations into parallel ones, maximizing the utilization of available CPU cores. + +### Running Benchmarks +To execute the benchmarks, navigate to the project's root directory and run the following command: + +```bash +make hyper-threading-benchmarks +``` diff --git a/examples/hyper_threading/hyper-threading.sh b/examples/hyper_threading/hyper-threading.sh new file mode 100644 index 0000000000..912b6cac75 --- /dev/null +++ b/examples/hyper_threading/hyper-threading.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +thread_counts=(1 2 4 6 8 10 12 16 24 32 ) +binary="target/release/hyper_threading" + + +cmd="hyperfine -r 1" + +# Build the command string with all thread counts +for threads in "${thread_counts[@]}"; do + # For hyperfine, wrap each command in 'sh -c' to correctly handle the environment variable + cmd+=" -n \"threads: ${threads}\" 'sh -c \"RAYON_NUM_THREADS=${threads} ${binary}\"'" +done + +# Execute the hyperfine command +echo "Executing benchmark for all thread counts" +eval $cmd diff --git a/examples/hyper_threading/src/main.rs b/examples/hyper_threading/src/main.rs new file mode 100644 index 0000000000..8c30082d5f --- /dev/null +++ b/examples/hyper_threading/src/main.rs @@ -0,0 +1,67 @@ +use cairo_vm::{ + cairo_run::{cairo_run_program, CairoRunConfig}, + hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor, + types::program::Program, +}; +use rayon::iter::{IntoParallelIterator, ParallelIterator}; + +// Define include_bytes_relative macro to prepend a relative path to the file names +macro_rules! include_bytes_relative { + ($fname:expr) => { + include_bytes!(concat!("../../../cairo_programs/benchmarks/", $fname)) + }; +} + +fn main() { + let mut programs = Vec::new(); + + let programs_bytes: [Vec; 18] = [ + include_bytes_relative!("big_factorial.json").to_vec(), + include_bytes_relative!("big_fibonacci.json").to_vec(), + include_bytes_relative!("blake2s_integration_benchmark.json").to_vec(), + include_bytes_relative!("compare_arrays_200000.json").to_vec(), + include_bytes_relative!("dict_integration_benchmark.json").to_vec(), + include_bytes_relative!("field_arithmetic_get_square_benchmark.json").to_vec(), + include_bytes_relative!("integration_builtins.json").to_vec(), + include_bytes_relative!("keccak_integration_benchmark.json").to_vec(), + include_bytes_relative!("linear_search.json").to_vec(), + include_bytes_relative!("math_cmp_and_pow_integration_benchmark.json").to_vec(), + include_bytes_relative!("math_integration_benchmark.json").to_vec(), + include_bytes_relative!("memory_integration_benchmark.json").to_vec(), + include_bytes_relative!("operations_with_data_structures_benchmarks.json").to_vec(), + include_bytes_relative!("pedersen.json").to_vec(), + include_bytes_relative!("poseidon_integration_benchmark.json").to_vec(), + include_bytes_relative!("secp_integration_benchmark.json").to_vec(), + include_bytes_relative!("set_integration_benchmark.json").to_vec(), + include_bytes_relative!("uint256_integration_benchmark.json").to_vec(), + ]; + + for bytes in &programs_bytes { + programs.push(Program::from_bytes(bytes.as_slice(), Some("main")).unwrap()) + } + + let start_time = std::time::Instant::now(); + + // Parallel execution of the program processing + programs.into_par_iter().for_each(|program| { + let cairo_run_config = CairoRunConfig { + entrypoint: "main", + trace_enabled: false, + relocate_mem: false, + layout: "all_cairo", + proof_mode: true, + secure_run: Some(false), + ..Default::default() + }; + let mut hint_executor = BuiltinHintProcessor::new_empty(); + + // Execute each program in parallel + let _result = cairo_run_program(&program, &cairo_run_config, &mut hint_executor) + .expect("Couldn't run program"); + }); + let elapsed = start_time.elapsed(); + + let programs_len: &usize = &programs_bytes.clone().len(); + + tracing::info!(%programs_len, ?elapsed, "Finished"); +}