From aaf86cd1742485034ad85212b8e5940625be9abb Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Wed, 20 Mar 2024 17:08:29 +0100 Subject: [PATCH 01/17] make `Matrix::invert` public --- src/linalg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linalg.rs b/src/linalg.rs index 48cac2a4..558f8913 100644 --- a/src/linalg.rs +++ b/src/linalg.rs @@ -135,7 +135,7 @@ impl<T: Field> Matrix<T> { } } - pub(super) fn invert(&self) -> Result<Self, KomodoError> { + pub fn invert(&self) -> Result<Self, KomodoError> { if self.height != self.width { return Err(KomodoError::NonSquareMatrix(self.height, self.width)); } -- GitLab From 2622e2942a1901851a7d36636fae821b29bedfe5 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Wed, 20 Mar 2024 17:04:53 +0100 Subject: [PATCH 02/17] add `linalg` benchmark and criterion --- Cargo.toml | 5 +++++ benches/linalg.rs | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 benches/linalg.rs diff --git a/Cargo.toml b/Cargo.toml index 6b2b45d0..9e65fa3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,8 @@ tracing-subscriber = "0.3.17" [dev-dependencies] rand = "0.8.5" +criterion = "0.3" + +[[bench]] +name = "linalg" +harness = false diff --git a/benches/linalg.rs b/benches/linalg.rs new file mode 100644 index 00000000..fdec2439 --- /dev/null +++ b/benches/linalg.rs @@ -0,0 +1,22 @@ +use ark_bls12_381::Bls12_381; +use ark_ec::pairing::Pairing; + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use komodo::linalg::Matrix; + +fn bench_template<E: Pairing>(c: &mut Criterion, n: usize) { + let matrix = Matrix::<E::ScalarField>::random(n, n); + + c.bench_function(&format!("inverse {}x{}", n, n), |b| { + b.iter(|| matrix.invert().unwrap()) + }); +} + +pub fn criterion_benchmark(c: &mut Criterion) { + for n in [10, 20, 30, 50, 100, 200] { + bench_template::<Bls12_381>(c, black_box(n)); + } +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); -- GitLab From f5b9beaf99de4e8502b0a7d72be029f52e716d28 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 11:23:16 +0100 Subject: [PATCH 03/17] minor tweaks to the benchmark --- benches/linalg.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/benches/linalg.rs b/benches/linalg.rs index fdec2439..79ebbf90 100644 --- a/benches/linalg.rs +++ b/benches/linalg.rs @@ -1,10 +1,10 @@ use ark_bls12_381::Bls12_381; use ark_ec::pairing::Pairing; - use criterion::{black_box, criterion_group, criterion_main, Criterion}; + use komodo::linalg::Matrix; -fn bench_template<E: Pairing>(c: &mut Criterion, n: usize) { +fn inverse_template<E: Pairing>(c: &mut Criterion, n: usize) { let matrix = Matrix::<E::ScalarField>::random(n, n); c.bench_function(&format!("inverse {}x{}", n, n), |b| { @@ -12,11 +12,11 @@ fn bench_template<E: Pairing>(c: &mut Criterion, n: usize) { }); } -pub fn criterion_benchmark(c: &mut Criterion) { - for n in [10, 20, 30, 50, 100, 200] { - bench_template::<Bls12_381>(c, black_box(n)); +fn inverse(c: &mut Criterion) { + for n in [10, 20, 40, 80, 160, 320] { + inverse_template::<Bls12_381>(c, black_box(n)); } } -criterion_group!(benches, criterion_benchmark); +criterion_group!(benches, inverse); criterion_main!(benches); -- GitLab From ae9b4e146d802ad367c8a3b985a99f31325316db Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 11:26:36 +0100 Subject: [PATCH 04/17] add curve name to benchmark name --- benches/linalg.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/benches/linalg.rs b/benches/linalg.rs index 79ebbf90..07634451 100644 --- a/benches/linalg.rs +++ b/benches/linalg.rs @@ -7,9 +7,10 @@ use komodo::linalg::Matrix; fn inverse_template<E: Pairing>(c: &mut Criterion, n: usize) { let matrix = Matrix::<E::ScalarField>::random(n, n); - c.bench_function(&format!("inverse {}x{}", n, n), |b| { - b.iter(|| matrix.invert().unwrap()) - }); + c.bench_function( + &format!("inverse {}x{} on {}", n, n, std::any::type_name::<E>()), + |b| b.iter(|| matrix.invert().unwrap()), + ); } fn inverse(c: &mut Criterion) { -- GitLab From c71f9ecc43d7a906eed45d00d996eacd3811da8d Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 11:45:40 +0100 Subject: [PATCH 05/17] add benchmark for `Matrix::transpose` --- benches/linalg.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/benches/linalg.rs b/benches/linalg.rs index 07634451..3414eb80 100644 --- a/benches/linalg.rs +++ b/benches/linalg.rs @@ -19,5 +19,21 @@ fn inverse(c: &mut Criterion) { } } +fn transpose_template<E: Pairing>(c: &mut Criterion, n: usize) { + let matrix = Matrix::<E::ScalarField>::random(n, n); + + c.bench_function( + &format!("transpose {}x{} on {}", n, n, std::any::type_name::<E>()), + |b| b.iter(|| matrix.transpose()), + ); +} + +fn transpose(c: &mut Criterion) { + for n in [10, 20, 40, 80, 160, 320] { + transpose_template::<Bls12_381>(c, black_box(n)); + } +} + criterion_group!(benches, inverse); +criterion_group!(benches, transpose); criterion_main!(benches); -- GitLab From f302177c1783bb4064f1bae32a0e75e6104e17bb Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 11:46:23 +0100 Subject: [PATCH 06/17] make `Matrix::transpose` public --- src/linalg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linalg.rs b/src/linalg.rs index 558f8913..557a9b5f 100644 --- a/src/linalg.rs +++ b/src/linalg.rs @@ -239,7 +239,7 @@ impl<T: Field> Matrix<T> { }) } - pub(super) fn transpose(&self) -> Self { + pub fn transpose(&self) -> Self { let height = self.width; let width = self.height; -- GitLab From a75aaf7a942b77572d436ead6282bc7671d0ebb9 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 11:47:12 +0100 Subject: [PATCH 07/17] fix criterion --- benches/linalg.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/benches/linalg.rs b/benches/linalg.rs index 3414eb80..66039fd8 100644 --- a/benches/linalg.rs +++ b/benches/linalg.rs @@ -34,6 +34,5 @@ fn transpose(c: &mut Criterion) { } } -criterion_group!(benches, inverse); -criterion_group!(benches, transpose); +criterion_group!(benches, inverse, transpose); criterion_main!(benches); -- GitLab From bc36582bcf2757a6e4293e5413224c81d3a4793c Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 11:48:52 +0100 Subject: [PATCH 08/17] make `Matrix::mul` public --- src/linalg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linalg.rs b/src/linalg.rs index 557a9b5f..26e726ba 100644 --- a/src/linalg.rs +++ b/src/linalg.rs @@ -209,7 +209,7 @@ impl<T: Field> Matrix<T> { nb_non_zero_rows } - pub(super) fn mul(&self, rhs: &Self) -> Result<Self, KomodoError> { + pub fn mul(&self, rhs: &Self) -> Result<Self, KomodoError> { if self.width != rhs.height { return Err(KomodoError::IncompatibleMatrixShapes( self.height, -- GitLab From fa0df045b2af9976a8bd5ad785988cc084cc8726 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 11:49:45 +0100 Subject: [PATCH 09/17] add mul benchmark --- benches/linalg.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/benches/linalg.rs b/benches/linalg.rs index 66039fd8..3e439f73 100644 --- a/benches/linalg.rs +++ b/benches/linalg.rs @@ -34,5 +34,21 @@ fn transpose(c: &mut Criterion) { } } -criterion_group!(benches, inverse, transpose); +fn mul_template<E: Pairing>(c: &mut Criterion, n: usize) { + let mat_a = Matrix::<E::ScalarField>::random(n, n); + let mat_b = Matrix::<E::ScalarField>::random(n, n); + + c.bench_function( + &format!("mul {}x{} on {}", n, n, std::any::type_name::<E>()), + |b| b.iter(|| mat_a.mul(&mat_b)), + ); +} + +fn mul(c: &mut Criterion) { + for n in [10, 20, 40, 80, 160, 320] { + mul_template::<Bls12_381>(c, black_box(n)); + } +} + +criterion_group!(benches, inverse, transpose, mul); criterion_main!(benches); -- GitLab From 284734a56076b7130d8aad00a0f6be345b405828 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 12:56:19 +0100 Subject: [PATCH 10/17] add a python script to plot the results --- benches/plot.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 benches/plot.py diff --git a/benches/plot.py b/benches/plot.py new file mode 100644 index 00000000..7eb810f7 --- /dev/null +++ b/benches/plot.py @@ -0,0 +1,43 @@ +import matplotlib.pyplot as plt +import json +from typing import Any, Dict, List + +RESULTS_FILE = "results.ndjson" +NB_NS_IN_MS = 1e6 + + +def plot(data: List[Dict[str, Any]], label: str, ax): + filtered_data = list(filter(lambda line: line["id"].startswith(label), data)) + + sizes = [ + int(line["id"].split(' ')[1].split('x')[0]) for line in filtered_data + ] + means = [ + line["mean"]["estimate"] / NB_NS_IN_MS for line in filtered_data + ] + + ax.plot(sizes, means, label=label) + + +if __name__ == "__main__": + with open(RESULTS_FILE, "r") as file: + data = list(filter( + lambda line: line["reason"] == "benchmark-complete", + map( + json.loads, + file.readlines() + ) + )) + + labels = ["transpose", "mul", "inverse"] + + fig, axs = plt.subplots(len(labels), 1) + + for label, ax in zip(labels, axs): + plot(data, label, ax) + ax.set_yscale("log") + ax.set_ylabel("time in ms") + ax.legend() + ax.grid() + + plt.show() -- GitLab From f9fb5e96de7c39ab9c29a6c4a4fc685d29c7d2e0 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 13:01:53 +0100 Subject: [PATCH 11/17] show the upper and lower bounds --- benches/plot.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/benches/plot.py b/benches/plot.py index 7eb810f7..b1268cfd 100644 --- a/benches/plot.py +++ b/benches/plot.py @@ -15,8 +15,15 @@ def plot(data: List[Dict[str, Any]], label: str, ax): means = [ line["mean"]["estimate"] / NB_NS_IN_MS for line in filtered_data ] + up = [ + line["mean"]["upper_bound"] / NB_NS_IN_MS for line in filtered_data + ] + down = [ + line["mean"]["lower_bound"] / NB_NS_IN_MS for line in filtered_data + ] ax.plot(sizes, means, label=label) + ax.fill_between(sizes, down, up, color="gray", alpha=0.3, label="bounds") if __name__ == "__main__": -- GitLab From 8692cef83e5591e17ac2fe54b1e6060bfd4128ea Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 13:08:58 +0100 Subject: [PATCH 12/17] add median and refactor --- benches/plot.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/benches/plot.py b/benches/plot.py index b1268cfd..2a0e880f 100644 --- a/benches/plot.py +++ b/benches/plot.py @@ -6,24 +6,30 @@ RESULTS_FILE = "results.ndjson" NB_NS_IN_MS = 1e6 +def extract(data: List[Dict[str, Any]], k1: str, k2: str) -> List[float]: + return [line[k1][k2] / NB_NS_IN_MS for line in data] + + def plot(data: List[Dict[str, Any]], label: str, ax): filtered_data = list(filter(lambda line: line["id"].startswith(label), data)) sizes = [ int(line["id"].split(' ')[1].split('x')[0]) for line in filtered_data ] - means = [ - line["mean"]["estimate"] / NB_NS_IN_MS for line in filtered_data - ] - up = [ - line["mean"]["upper_bound"] / NB_NS_IN_MS for line in filtered_data - ] - down = [ - line["mean"]["lower_bound"] / NB_NS_IN_MS for line in filtered_data - ] - ax.plot(sizes, means, label=label) - ax.fill_between(sizes, down, up, color="gray", alpha=0.3, label="bounds") + means = extract(filtered_data, "mean", "estimate") + up = extract(filtered_data, "mean", "upper_bound") + down = extract(filtered_data, "mean", "lower_bound") + + ax.plot(sizes, means, label="mean", color="blue") + ax.fill_between(sizes, down, up, color="blue", alpha=0.3, label="mean bounds") + + medians = extract(filtered_data, "median", "estimate") + up = extract(filtered_data, "median", "upper_bound") + down = extract(filtered_data, "median", "lower_bound") + + ax.plot(sizes, medians, label="median", color="orange") + ax.fill_between(sizes, down, up, color="orange", alpha=0.3, label="median bounds") if __name__ == "__main__": @@ -42,6 +48,7 @@ if __name__ == "__main__": for label, ax in zip(labels, axs): plot(data, label, ax) + ax.set_title(label) ax.set_yscale("log") ax.set_ylabel("time in ms") ax.legend() -- GitLab From 7c1ec44cdd850720f0ba561172b25495c229da69 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 13:10:24 +0100 Subject: [PATCH 13/17] refactor --- benches/plot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/benches/plot.py b/benches/plot.py index 2a0e880f..fdc1e989 100644 --- a/benches/plot.py +++ b/benches/plot.py @@ -10,8 +10,8 @@ def extract(data: List[Dict[str, Any]], k1: str, k2: str) -> List[float]: return [line[k1][k2] / NB_NS_IN_MS for line in data] -def plot(data: List[Dict[str, Any]], label: str, ax): - filtered_data = list(filter(lambda line: line["id"].startswith(label), data)) +def plot(data: List[Dict[str, Any]], key: str, ax): + filtered_data = list(filter(lambda line: line["id"].startswith(key), data)) sizes = [ int(line["id"].split(' ')[1].split('x')[0]) for line in filtered_data @@ -47,7 +47,7 @@ if __name__ == "__main__": fig, axs = plt.subplots(len(labels), 1) for label, ax in zip(labels, axs): - plot(data, label, ax) + plot(data, key=label, ax=ax) ax.set_title(label) ax.set_yscale("log") ax.set_ylabel("time in ms") -- GitLab From f7395a5810058b10cbfbbeba436c8ae26005aba6 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 13:16:28 +0100 Subject: [PATCH 14/17] pass filename as argument and refactor --- benches/plot.py | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/benches/plot.py b/benches/plot.py index fdc1e989..08b17c60 100644 --- a/benches/plot.py +++ b/benches/plot.py @@ -1,16 +1,19 @@ import matplotlib.pyplot as plt import json +import sys +import os from typing import Any, Dict, List -RESULTS_FILE = "results.ndjson" NB_NS_IN_MS = 1e6 +Data = List[Dict[str, Any]] -def extract(data: List[Dict[str, Any]], k1: str, k2: str) -> List[float]: + +def extract(data: Data, k1: str, k2: str) -> List[float]: return [line[k1][k2] / NB_NS_IN_MS for line in data] -def plot(data: List[Dict[str, Any]], key: str, ax): +def plot(data: Data, key: str, ax): filtered_data = list(filter(lambda line: line["id"].startswith(key), data)) sizes = [ @@ -32,8 +35,20 @@ def plot(data: List[Dict[str, Any]], key: str, ax): ax.fill_between(sizes, down, up, color="orange", alpha=0.3, label="median bounds") -if __name__ == "__main__": - with open(RESULTS_FILE, "r") as file: +def parse_args(): + if len(sys.argv) == 1: + print("please give a filename as first positional argument") + exit(1) + + return sys.argv[1] + + +def read_data(data_file: str) -> Data: + if not os.path.exists(data_file): + print(f"no such file: `{data_file}`") + exit(1) + + with open(data_file, "r") as file: data = list(filter( lambda line: line["reason"] == "benchmark-complete", map( @@ -42,6 +57,13 @@ if __name__ == "__main__": ) )) + return data + + +if __name__ == "__main__": + results_file = parse_args() + data = read_data(results_file) + labels = ["transpose", "mul", "inverse"] fig, axs = plt.subplots(len(labels), 1) -- GitLab From 58708668fe7b666af32d64e6fbaf8f91d80683c6 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 13:17:37 +0100 Subject: [PATCH 15/17] add a README --- benches/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 benches/README.md diff --git a/benches/README.md b/benches/README.md new file mode 100644 index 00000000..9867ccd1 --- /dev/null +++ b/benches/README.md @@ -0,0 +1,9 @@ +## run the benchmarks +```shell +nushell> cargo criterion --output-format verbose --message-format json out> results.ndjson +``` + +## plot the results +```shell +python benches/plot.py results.ndjson +``` -- GitLab From 707c56833106b7b303241459d658aa159d8e72fc Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 13:17:59 +0100 Subject: [PATCH 16/17] ignore result files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 2c96eb1b..e2b32eb7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ target/ Cargo.lock + +*.ndjson -- GitLab From 32d1655f2a173adf2091d689b77715f0877823ff Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 22 Mar 2024 13:23:21 +0100 Subject: [PATCH 17/17] add more benchmark points --- benches/linalg.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/benches/linalg.rs b/benches/linalg.rs index 3e439f73..21528738 100644 --- a/benches/linalg.rs +++ b/benches/linalg.rs @@ -14,7 +14,7 @@ fn inverse_template<E: Pairing>(c: &mut Criterion, n: usize) { } fn inverse(c: &mut Criterion) { - for n in [10, 20, 40, 80, 160, 320] { + for n in [10, 15, 20, 30, 40, 60, 80, 120, 160, 240, 320] { inverse_template::<Bls12_381>(c, black_box(n)); } } @@ -29,7 +29,7 @@ fn transpose_template<E: Pairing>(c: &mut Criterion, n: usize) { } fn transpose(c: &mut Criterion) { - for n in [10, 20, 40, 80, 160, 320] { + for n in [10, 15, 20, 30, 40, 60, 80, 120, 160, 240, 320] { transpose_template::<Bls12_381>(c, black_box(n)); } } @@ -45,7 +45,7 @@ fn mul_template<E: Pairing>(c: &mut Criterion, n: usize) { } fn mul(c: &mut Criterion) { - for n in [10, 20, 40, 80, 160, 320] { + for n in [10, 15, 20, 30, 40, 60, 80, 120, 160, 240, 320] { mul_template::<Bls12_381>(c, black_box(n)); } } -- GitLab