Skip to content

Commit 6508041

Browse files
author
AztecBot
committed
Merge branch 'next' into merge-train/avm
2 parents 8a8cc7f + d77a75b commit 6508041

34 files changed

+974
-627
lines changed
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
#!/bin/bash
2+
3+
# CPU scaling benchmark wrapper that uses benchmark_remote.sh properly
4+
# This script runs a command multiple times with different HARDWARE_CONCURRENCY values
5+
# and tracks the scaling performance of specific BB_BENCH entries
6+
# Uses --bench_out flag to get JSON output for accurate timing extraction
7+
8+
set -e
9+
10+
# Colors for output
11+
RED='\033[0;31m'
12+
GREEN='\033[0;32m'
13+
YELLOW='\033[1;33m'
14+
BLUE='\033[0;34m'
15+
CYAN='\033[0;36m'
16+
MAGENTA='\033[0;35m'
17+
NC='\033[0m' # No Color
18+
19+
# Parse arguments
20+
if [ $# -lt 2 ]; then
21+
echo -e "${RED}Usage: $0 \"benchmark_name\" \"command\" [cpu_counts]${NC}"
22+
echo -e "Example: $0 \"ClientIvcProve\" \"./build/bin/bb prove --ivc_inputs_path input.msgpack --scheme client_ivc\""
23+
echo -e "Example: $0 \"construct_mock_function_circuit\" \"./build/bin/ultra_honk_bench --benchmark_filter=.*power_of_2.*/15\" \"1,2,4,8\""
24+
exit 1
25+
fi
26+
27+
BENCH_NAME="$1"
28+
COMMAND="$2"
29+
CPU_LIST="${3:-1,2,4,8,16}"
30+
31+
# Convert comma-separated list to array
32+
IFS=',' read -ra CPU_COUNTS <<< "$CPU_LIST"
33+
34+
# Check if required environment variables are set for remote execution
35+
if [ -z "${BB_SSH_KEY:-}" ] || [ -z "${BB_SSH_INSTANCE:-}" ] || [ -z "${BB_SSH_CPP_PATH:-}" ]; then
36+
echo -e "${RED}Error: Remote execution requires BB_SSH_KEY, BB_SSH_INSTANCE, and BB_SSH_CPP_PATH environment variables${NC}"
37+
echo "Please set:"
38+
echo " export BB_SSH_KEY='-i /path/to/key.pem'"
39+
echo " export BB_SSH_INSTANCE='[email protected]'"
40+
echo " export BB_SSH_CPP_PATH='/path/to/barretenberg/cpp'"
41+
exit 1
42+
fi
43+
44+
# Create output directory with timestamp
45+
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
46+
OUTPUT_DIR="bench_scaling_remote_${TIMESTAMP}"
47+
mkdir -p "$OUTPUT_DIR"
48+
49+
# Results file
50+
RESULTS_FILE="$OUTPUT_DIR/scaling_results.txt"
51+
CSV_FILE="$OUTPUT_DIR/scaling_results.csv"
52+
53+
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
54+
echo -e "${GREEN}║ CPU Scaling Benchmark (Remote Execution) ║${NC}"
55+
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
56+
echo ""
57+
echo -e "${CYAN}Benchmark Entry:${NC} ${YELLOW}$BENCH_NAME${NC}"
58+
echo -e "${CYAN}Command:${NC} $COMMAND"
59+
echo -e "${CYAN}CPU Counts:${NC} ${CPU_COUNTS[@]}"
60+
echo -e "${CYAN}Remote Host:${NC} ${BB_SSH_INSTANCE}"
61+
echo -e "${CYAN}Remote Path:${NC} ${BB_SSH_CPP_PATH}"
62+
echo -e "${CYAN}Output Directory:${NC} $OUTPUT_DIR"
63+
echo ""
64+
65+
# Initialize results file
66+
echo "CPU Scaling Benchmark: $BENCH_NAME" > "$RESULTS_FILE"
67+
echo "Command: $COMMAND" >> "$RESULTS_FILE"
68+
echo "Remote Host: $BB_SSH_INSTANCE" >> "$RESULTS_FILE"
69+
echo "Date: $(date)" >> "$RESULTS_FILE"
70+
echo "================================================" >> "$RESULTS_FILE"
71+
echo "" >> "$RESULTS_FILE"
72+
73+
# Initialize CSV file
74+
echo "CPUs,Time_ms,Time_s,Speedup,Efficiency" > "$CSV_FILE"
75+
76+
# Function to extract time for specific benchmark entry from JSON
77+
extract_bench_time() {
78+
local json_file=$1
79+
local bench_name=$2
80+
81+
# Extract time from JSON file using grep and sed
82+
# JSON format is: {"benchmark_name": time_in_nanoseconds, ...}
83+
local time_ns=""
84+
85+
if [ -f "$json_file" ]; then
86+
# Extract the value for the specific benchmark name from JSON
87+
time_ns=$(grep -oP "\"${bench_name//\\/\\\\}\":\s*\K\d+" "$json_file" 2>/dev/null | head -1)
88+
fi
89+
90+
# If JSON extraction failed, try to extract from log file (fallback)
91+
if [ -z "$time_ns" ] && [ -f "${json_file%/bench.json}/output.log" ]; then
92+
local log_file="${json_file%/bench.json}/output.log"
93+
# Try to extract from hierarchical BB_BENCH output
94+
# Look for pattern like: " ├─ ClientIvcProve ... 28.13s"
95+
local time_s=$(grep -E "├─.*${bench_name}" "$log_file" | grep -oP '\d+\.\d+s' | grep -oP '\d+\.\d+' | head -1)
96+
if [ -n "$time_s" ]; then
97+
# Convert seconds to nanoseconds
98+
time_ns=$(awk -v s="$time_s" 'BEGIN{printf "%.0f", s * 1000000000}')
99+
fi
100+
fi
101+
102+
echo "$time_ns"
103+
}
104+
105+
# Store baseline time for speedup calculation
106+
BASELINE_TIME=""
107+
108+
# Arrays to store results
109+
declare -a ALL_CPUS=()
110+
declare -a ALL_TIMES=()
111+
declare -a ALL_SPEEDUPS=()
112+
113+
echo -e "${BLUE}Starting benchmark runs on remote machine...${NC}"
114+
echo ""
115+
116+
# Run benchmark for each CPU count
117+
for cpu_count in "${CPU_COUNTS[@]}"; do
118+
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
119+
echo -e "${YELLOW}Running with ${cpu_count} CPU(s)...${NC}"
120+
121+
# Create output subdirectory
122+
run_dir="$OUTPUT_DIR/run_${cpu_count}cpus"
123+
mkdir -p "$run_dir"
124+
log_file="$run_dir/output.log"
125+
126+
# Run command on remote machine with specified CPU count
127+
echo -e "${CYAN}Executing on remote via benchmark_remote.sh...${NC}"
128+
start_time=$(date +%s.%N)
129+
130+
# Use benchmark_remote.sh to execute on remote with --bench_out for JSON output
131+
# The benchmark_remote.sh script handles locking and setup
132+
# Use tee to show output in real-time AND save to log file
133+
bench_json_file="$run_dir/bench.json"
134+
./scripts/benchmark_remote.sh bb "HARDWARE_CONCURRENCY=$cpu_count $COMMAND --bench_out /tmp/bench_${cpu_count}.json" 2>&1 | tee "$log_file"
135+
136+
# Retrieve the JSON file from remote
137+
ssh $BB_SSH_KEY $BB_SSH_INSTANCE "cat /tmp/bench_${cpu_count}.json" > "$bench_json_file" 2>/dev/null
138+
139+
end_time=$(date +%s.%N)
140+
wall_time=$(awk -v e="$end_time" -v s="$start_time" 'BEGIN{printf "%.2f", e-s}')
141+
142+
# Extract the specific benchmark time from JSON file
143+
bench_time_ns=$(extract_bench_time "$bench_json_file" "$BENCH_NAME")
144+
145+
if [ -z "$bench_time_ns" ] || [ "$bench_time_ns" = "0" ]; then
146+
echo -e "${RED}Warning: Could not extract timing for '$BENCH_NAME' from JSON${NC}"
147+
echo -e "${YELLOW}Check the JSON file: $bench_json_file${NC}"
148+
149+
# Show what's in the JSON file for debugging
150+
if [ -f "$bench_json_file" ]; then
151+
echo -e "${YELLOW}JSON content (first 500 chars):${NC}"
152+
head -c 500 "$bench_json_file"
153+
echo ""
154+
fi
155+
156+
echo "CPUs: $cpu_count - No timing data found" >> "$RESULTS_FILE"
157+
continue
158+
fi
159+
160+
# Convert to milliseconds and seconds
161+
bench_time_ms=$(awk -v ns="$bench_time_ns" 'BEGIN{printf "%.2f", ns / 1000000}')
162+
bench_time_s=$(awk -v ns="$bench_time_ns" 'BEGIN{printf "%.3f", ns / 1000000000}')
163+
164+
# Calculate speedup and efficiency
165+
if [ -z "$BASELINE_TIME" ]; then
166+
BASELINE_TIME="$bench_time_ns"
167+
speedup="1.00"
168+
efficiency="100.0"
169+
else
170+
speedup=$(awk -v base="$BASELINE_TIME" -v curr="$bench_time_ns" 'BEGIN{printf "%.2f", base / curr}')
171+
efficiency=$(awk -v sp="$speedup" -v cpus="$cpu_count" 'BEGIN{printf "%.1f", (sp / cpus) * 100}')
172+
fi
173+
174+
# Store results
175+
ALL_CPUS+=("$cpu_count")
176+
ALL_TIMES+=("$bench_time_ms")
177+
ALL_SPEEDUPS+=("$speedup")
178+
179+
# Write to results file
180+
echo "CPUs: $cpu_count" >> "$RESULTS_FILE"
181+
echo " Time: ${bench_time_ms} ms (${bench_time_s} s)" >> "$RESULTS_FILE"
182+
echo " Speedup: ${speedup}x" >> "$RESULTS_FILE"
183+
echo " Efficiency: ${efficiency}%" >> "$RESULTS_FILE"
184+
echo " Wall time: ${wall_time}s" >> "$RESULTS_FILE"
185+
echo "" >> "$RESULTS_FILE"
186+
187+
# Write to CSV
188+
echo "$cpu_count,$bench_time_ms,$bench_time_s,$speedup,$efficiency" >> "$CSV_FILE"
189+
190+
# Display results
191+
echo -e "${GREEN}✓ Completed${NC}"
192+
echo -e " ${CYAN}Time for '$BENCH_NAME':${NC} ${bench_time_ms} ms"
193+
echo -e " ${CYAN}Speedup:${NC} ${speedup}x"
194+
echo -e " ${CYAN}Efficiency:${NC} ${efficiency}%"
195+
echo ""
196+
done
197+
198+
# Generate summary
199+
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
200+
echo -e "${GREEN}║ SUMMARY ║${NC}"
201+
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
202+
echo ""
203+
204+
# Print table header
205+
printf "${CYAN}%-8s %-15s %-12s %-12s${NC}\n" "CPUs" "Time (ms)" "Speedup" "Efficiency"
206+
printf "${CYAN}%-8s %-15s %-12s %-12s${NC}\n" "────" "──────────" "───────" "──────────"
207+
208+
# Print results table
209+
for i in "${!ALL_CPUS[@]}"; do
210+
cpu="${ALL_CPUS[$i]}"
211+
time="${ALL_TIMES[$i]}"
212+
speedup="${ALL_SPEEDUPS[$i]}"
213+
214+
if [ "$i" -eq 0 ]; then
215+
efficiency="100.0%"
216+
else
217+
efficiency=$(awk -v sp="$speedup" -v cpus="$cpu" 'BEGIN{printf "%.1f%%", (sp / cpus) * 100}')
218+
fi
219+
220+
# Color code based on efficiency
221+
if [ "$i" -eq 0 ]; then
222+
color="${GREEN}"
223+
else
224+
eff_val=$(echo "$efficiency" | sed 's/%//')
225+
if (( $(echo "$eff_val > 75" | bc -l) )); then
226+
color="${GREEN}"
227+
elif (( $(echo "$eff_val > 50" | bc -l) )); then
228+
color="${YELLOW}"
229+
else
230+
color="${RED}"
231+
fi
232+
fi
233+
234+
printf "${color}%-8s %-15s %-12s %-12s${NC}\n" "$cpu" "$time" "${speedup}x" "$efficiency"
235+
done
236+
237+
echo ""
238+
echo -e "${MAGENTA}═══════════════════════════════════════════════════════════════${NC}"
239+
echo ""
240+
241+
# Generate scaling plot (ASCII art)
242+
echo -e "${CYAN}Scaling Visualization:${NC}"
243+
echo ""
244+
245+
if [ "${#ALL_TIMES[@]}" -gt 0 ]; then
246+
# Find max time for scaling
247+
max_time=$(printf '%s\n' "${ALL_TIMES[@]}" | sort -rn | head -1)
248+
249+
# Create ASCII bar chart
250+
for i in "${!ALL_CPUS[@]}"; do
251+
cpu="${ALL_CPUS[$i]}"
252+
time="${ALL_TIMES[$i]}"
253+
254+
# Calculate bar length (max 50 chars)
255+
bar_len=$(awk -v t="$time" -v m="$max_time" 'BEGIN{printf "%.0f", (t/m) * 50}')
256+
257+
# Create bar
258+
bar=""
259+
for ((j=0; j<bar_len; j++)); do
260+
bar="${bar}"
261+
done
262+
263+
printf "%-6s │%s %.2f ms\n" "${cpu} CPU" "$bar" "$time"
264+
done
265+
fi
266+
267+
echo ""
268+
echo -e "${GREEN}Results saved to:${NC}"
269+
echo " - Summary: $RESULTS_FILE"
270+
echo " - CSV: $CSV_FILE"
271+
echo " - Logs: $OUTPUT_DIR/run_*cpus/output.log"
272+
echo ""
273+
274+
# Check for scaling issues
275+
if [ "${#ALL_SPEEDUPS[@]}" -gt 1 ]; then
276+
last_speedup="${ALL_SPEEDUPS[-1]}"
277+
last_cpu="${ALL_CPUS[-1]}"
278+
actual_efficiency=$(awk -v sp="$last_speedup" -v cpus="$last_cpu" 'BEGIN{printf "%.1f", (sp / cpus) * 100}')
279+
280+
if (( $(echo "$actual_efficiency < 50" | bc -l) )); then
281+
echo -e "${YELLOW}⚠ Warning: Poor scaling detected!${NC}"
282+
echo -e " At ${last_cpu} CPUs: ${actual_efficiency}% efficiency"
283+
echo -e " Consider investigating thread contention or memory bottlenecks."
284+
elif (( $(echo "$actual_efficiency < 75" | bc -l) )); then
285+
echo -e "${YELLOW}Note: Moderate scaling efficiency at high CPU counts.${NC}"
286+
echo -e " At ${last_cpu} CPUs: ${actual_efficiency}% efficiency"
287+
else
288+
echo -e "${GREEN}✓ Good scaling efficiency maintained!${NC}"
289+
echo -e " At ${last_cpu} CPUs: ${actual_efficiency}% efficiency"
290+
fi
291+
fi
292+
293+
echo ""

barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ bool ClientIVCAPI::prove_and_verify(const std::filesystem::path& input_path)
130130
std::shared_ptr<ClientIVC> ivc = steps.accumulate();
131131
// Construct the hiding kernel as the final step of the IVC
132132

133-
const bool verified = ivc->prove_and_verify();
133+
auto proof = ivc->prove();
134+
const bool verified = ClientIVC::verify(proof, ivc->get_vk());
134135
return verified;
135136
}
136137

barretenberg/cpp/src/barretenberg/bbapi/bbapi_client_ivc.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ ClientIvcProve::Response ClientIvcProve::execute(BBApiRequest& request) &&
8686
// We verify this proof. Another bb call to verify has some overhead of loading VK/proof/SRS,
8787
// and it is mysterious if this transaction fails later in the lifecycle.
8888
info("ClientIvcProve - verifying the generated proof as a sanity check");
89-
if (!request.ivc_in_progress->verify(proof)) {
89+
ClientIVC::VerificationKey vk = request.ivc_in_progress->get_vk();
90+
if (!ClientIVC::verify(proof, vk)) {
9091
throw_or_abort("Failed to verify the generated proof!");
9192
}
9293

0 commit comments

Comments
 (0)