From fb51e005030fa3fa5e039a1475de2d93ae2bf184 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 13 Aug 2024 13:14:54 -0700 Subject: [PATCH 1/7] Remove unnecessary type annotations These annotations are only needed for statically sized matrices. --- lang-trials/rust-benchmark/src/engine.rs | 22 ++-------------------- lang-trials/rust-benchmark/src/main.rs | 3 ++- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/lang-trials/rust-benchmark/src/engine.rs b/lang-trials/rust-benchmark/src/engine.rs index a2661aa..04377fd 100644 --- a/lang-trials/rust-benchmark/src/engine.rs +++ b/lang-trials/rust-benchmark/src/engine.rs @@ -4,17 +4,8 @@ use std::f64::consts::{PI, E}; /*use typenum::{B1, UInt, UTerm};*/ /* dynamic matrices */ -pub fn rand_eigval_series(time_res: usize) -> Vec, Dyn>> - where - N: ToTypenum + DimName + DimSub, - DefaultAllocator: - Allocator + - Allocator + - Allocator<>::Output> + - Allocator>::Output> -{ +pub fn rand_eigval_series(dim: usize, time_res: usize) -> Vec, Dyn>> { // initialize the random matrix - let dim = N::try_to_usize().unwrap(); let mut rand_mat = DMatrix::::from_fn(dim, dim, |j, k| { let n = j*dim + k; E*((n*n) as f64) % 2.0 - 1.0 @@ -44,17 +35,8 @@ pub fn rand_eigval_series(time_res: usize) -> Vec, Dyn>> } /* dynamic single float matrices */ -/*pub fn rand_eigval_series(time_res: usize) -> Vec, Dyn>> - where - N: ToTypenum + DimName + DimSub, - DefaultAllocator: - Allocator + - Allocator + - Allocator<>::Output> + - Allocator>::Output> -{ +/*pub fn rand_eigval_series(dim: usize, time_res: usize) -> Vec, Dyn>> { // initialize the random matrix - let dim = N::try_to_usize().unwrap(); let mut rand_mat = DMatrix::::from_fn(dim, dim, |j, k| { let n = j*dim + k; (E as f32)*((n*n) as f32) % 2.0_f32 - 1.0_f32 diff --git a/lang-trials/rust-benchmark/src/main.rs b/lang-trials/rust-benchmark/src/main.rs index 9662dd7..01364e5 100644 --- a/lang-trials/rust-benchmark/src/main.rs +++ b/lang-trials/rust-benchmark/src/main.rs @@ -19,7 +19,8 @@ fn main() { on_mount(move || { let performance = window().unwrap().performance().unwrap(); let start_time = performance.now(); - let eigval_series = engine::rand_eigval_series::(time_res); + /*let eigval_series = engine::rand_eigval_series::(time_res);*/ + let eigval_series = engine::rand_eigval_series(60, time_res); let run_time = performance.now() - start_time; run_time_report.set(run_time); From d864ab5abe1dcbd551a332650bed42a19fa46bd7 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 13 Aug 2024 13:29:58 -0700 Subject: [PATCH 2/7] Drop second attempt at static matrices I couldn't get this one working, and the first attempt seems fine. --- lang-trials/rust-benchmark/src/engine.rs | 41 ------------------------ 1 file changed, 41 deletions(-) diff --git a/lang-trials/rust-benchmark/src/engine.rs b/lang-trials/rust-benchmark/src/engine.rs index 04377fd..eed73a1 100644 --- a/lang-trials/rust-benchmark/src/engine.rs +++ b/lang-trials/rust-benchmark/src/engine.rs @@ -1,7 +1,5 @@ use nalgebra::{*, allocator::Allocator}; use std::f64::consts::{PI, E}; -/*use std::ops::Sub;*/ -/*use typenum::{B1, UInt, UTerm};*/ /* dynamic matrices */ pub fn rand_eigval_series(dim: usize, time_res: usize) -> Vec, Dyn>> { @@ -104,43 +102,4 @@ pub fn rand_eigval_series(dim: usize, time_res: usize) -> Vec(time_res: usize) -> Vec, Const>> - where - Const: ToTypenum, - as ToTypenum>::Typenum: Sub>, - < as ToTypenum>::Typenum as Sub>>::Output: ToConst -{ - // initialize the random matrix - /*let mut rand_mat = SMatrix::::zeros(); - for n in 0..N*N { - rand_mat[n] = E*((n*n) as f64) % 2.0 - 1.0; - }*/ - let rand_mat = OMatrix::, Const>::from_fn(|j, k| { - let n = j*N + k; - E*((n*n) as f64) % 2.0 - 1.0 - }); - - // initialize the rotation step - let mut rot_step = OMatrix::, Const>::identity(); - let max_freq = 4; - for n in (0..N).step_by(2) { - let ang = PI * ((n % max_freq) as f64) / (time_res as f64); - let ang_cos = ang.cos(); - let ang_sin = ang.sin(); - rot_step[(n, n)] = ang_cos; - rot_step[(n+1, n)] = ang_sin; - rot_step[(n, n+1)] = -ang_sin; - rot_step[(n+1, n+1)] = ang_cos; - } - - // find the eigenvalues - let mut eigvals = Vec::, Const>>::with_capacity(time_res); - unsafe { eigvals.set_len(time_res); } - for t in 0..time_res { - eigvals[t] = rand_mat.complex_eigenvalues(); - } - eigvals }*/ \ No newline at end of file From 0abcb995b590133e522147b10e5fe60ac36d764e Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 13 Aug 2024 13:40:33 -0700 Subject: [PATCH 3/7] Rust benchmark: rename package --- lang-trials/rust-benchmark/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang-trials/rust-benchmark/Cargo.toml b/lang-trials/rust-benchmark/Cargo.toml index 8dde7b0..c3ad0ae 100644 --- a/lang-trials/rust-benchmark/Cargo.toml +++ b/lang-trials/rust-benchmark/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sycamore-trial" +name = "rust-benchmark" version = "0.1.0" authors = ["Aaron"] edition = "2021" From 543f348cd8bec80942059b215ee17e090c7af33e Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 13 Aug 2024 13:47:34 -0700 Subject: [PATCH 4/7] Rust benchmark: drop old debug code --- lang-trials/rust-benchmark/src/engine.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/lang-trials/rust-benchmark/src/engine.rs b/lang-trials/rust-benchmark/src/engine.rs index eed73a1..3aca755 100644 --- a/lang-trials/rust-benchmark/src/engine.rs +++ b/lang-trials/rust-benchmark/src/engine.rs @@ -79,7 +79,6 @@ pub fn rand_eigval_series(dim: usize, time_res: usize) -> Vec::identity();*/ // initialize the rotation step let mut rot_step = OMatrix::::identity(); From 8ce3e251d79bc1714f31ad3eefe61e1e5733b656 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 13 Aug 2024 13:51:54 -0700 Subject: [PATCH 5/7] Drop unused dependency and `use` declaration --- lang-trials/rust-benchmark/Cargo.toml | 1 - lang-trials/rust-benchmark/src/main.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/lang-trials/rust-benchmark/Cargo.toml b/lang-trials/rust-benchmark/Cargo.toml index c3ad0ae..c3dfc0b 100644 --- a/lang-trials/rust-benchmark/Cargo.toml +++ b/lang-trials/rust-benchmark/Cargo.toml @@ -10,7 +10,6 @@ default = ["console_error_panic_hook"] [dependencies] nalgebra = "0.33.0" sycamore = "0.9.0-beta.2" -typenum = "1.17.0" # The `console_error_panic_hook` crate provides better debugging of panics by # logging them with `console.error`. This is great for development, but requires diff --git a/lang-trials/rust-benchmark/src/main.rs b/lang-trials/rust-benchmark/src/main.rs index 01364e5..da70362 100644 --- a/lang-trials/rust-benchmark/src/main.rs +++ b/lang-trials/rust-benchmark/src/main.rs @@ -1,4 +1,3 @@ -use nalgebra::*; use std::f64::consts::PI as PI; use sycamore::{prelude::*, rt::{JsCast, JsValue}}; use web_sys::window; From eeb0f00534f05bb633de175649ef105e47b4d0c2 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Mon, 19 Aug 2024 12:20:56 -0700 Subject: [PATCH 6/7] Rust benchmark: write native version --- lang-trials/rust-benchmark-native/.gitignore | 3 + lang-trials/rust-benchmark-native/Cargo.toml | 18 +++ .../rust-benchmark-native/src/engine.rs | 105 +++++++++++++++++ lang-trials/rust-benchmark-native/src/main.rs | 110 ++++++++++++++++++ 4 files changed, 236 insertions(+) create mode 100644 lang-trials/rust-benchmark-native/.gitignore create mode 100644 lang-trials/rust-benchmark-native/Cargo.toml create mode 100644 lang-trials/rust-benchmark-native/src/engine.rs create mode 100644 lang-trials/rust-benchmark-native/src/main.rs diff --git a/lang-trials/rust-benchmark-native/.gitignore b/lang-trials/rust-benchmark-native/.gitignore new file mode 100644 index 0000000..5b910ca --- /dev/null +++ b/lang-trials/rust-benchmark-native/.gitignore @@ -0,0 +1,3 @@ +target/* +dist/* +Cargo.lock \ No newline at end of file diff --git a/lang-trials/rust-benchmark-native/Cargo.toml b/lang-trials/rust-benchmark-native/Cargo.toml new file mode 100644 index 0000000..0ed8747 --- /dev/null +++ b/lang-trials/rust-benchmark-native/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "rust-benchmark-native" +version = "0.1.0" +authors = ["Aaron"] +edition = "2021" + +[dependencies] +cairo-rs = "0.20.1" +gtk = { package = "gtk4", version = "0.9.0" } +##minifb = "0.27.0" +nalgebra = "0.33.0" +plotters = "0.3.6" +plotters-cairo = "0.7.0" +##plotters-gtk4 = { git = "https://github.com/baarkerlounger/plotters-gtk4.git", branch = "patch-1" } + +[profile.release] +opt-level = "s" # optimize for small code size +debug = true # include debug symbols diff --git a/lang-trials/rust-benchmark-native/src/engine.rs b/lang-trials/rust-benchmark-native/src/engine.rs new file mode 100644 index 0000000..eed73a1 --- /dev/null +++ b/lang-trials/rust-benchmark-native/src/engine.rs @@ -0,0 +1,105 @@ +use nalgebra::{*, allocator::Allocator}; +use std::f64::consts::{PI, E}; + +/* dynamic matrices */ +pub fn rand_eigval_series(dim: usize, time_res: usize) -> Vec, Dyn>> { + // initialize the random matrix + let mut rand_mat = DMatrix::::from_fn(dim, dim, |j, k| { + let n = j*dim + k; + E*((n*n) as f64) % 2.0 - 1.0 + }) * (3.0 / (dim as f64)).sqrt(); + + // initialize the rotation step + let mut rot_step = DMatrix::::identity(dim, dim); + let max_freq = 4; + for n in (0..dim).step_by(2) { + let ang = PI * ((n % max_freq) as f64) / (time_res as f64); + let ang_cos = ang.cos(); + let ang_sin = ang.sin(); + rot_step[(n, n)] = ang_cos; + rot_step[(n+1, n)] = ang_sin; + rot_step[(n, n+1)] = -ang_sin; + rot_step[(n+1, n+1)] = ang_cos; + } + + // find the eigenvalues + let mut eigval_series = Vec::, Dyn>>::with_capacity(time_res); + eigval_series.push(rand_mat.complex_eigenvalues()); + for _ in 1..time_res { + rand_mat = &rot_step * rand_mat; + eigval_series.push(rand_mat.complex_eigenvalues()); + } + eigval_series +} + +/* dynamic single float matrices */ +/*pub fn rand_eigval_series(dim: usize, time_res: usize) -> Vec, Dyn>> { + // initialize the random matrix + let mut rand_mat = DMatrix::::from_fn(dim, dim, |j, k| { + let n = j*dim + k; + (E as f32)*((n*n) as f32) % 2.0_f32 - 1.0_f32 + }) * (3.0_f32 / (dim as f32)).sqrt(); + + // initialize the rotation step + let mut rot_step = DMatrix::::identity(dim, dim); + let max_freq = 4; + for n in (0..dim).step_by(2) { + let ang = (PI as f32) * ((n % max_freq) as f32) / (time_res as f32); + let ang_cos = ang.cos(); + let ang_sin = ang.sin(); + rot_step[(n, n)] = ang_cos; + rot_step[(n+1, n)] = ang_sin; + rot_step[(n, n+1)] = -ang_sin; + rot_step[(n+1, n+1)] = ang_cos; + } + + // find the eigenvalues + let mut eigval_series = Vec::, Dyn>>::with_capacity(time_res); + eigval_series.push(rand_mat.complex_eigenvalues()); + for _ in 1..time_res { + rand_mat = &rot_step * rand_mat; + eigval_series.push(rand_mat.complex_eigenvalues()); + } + eigval_series +}*/ + +/* static matrices. should only be used when the dimension is really small */ +/*pub fn rand_eigval_series(time_res: usize) -> Vec, N>> + where + N: ToTypenum + DimName + DimSub, + DefaultAllocator: + Allocator + + Allocator + + Allocator<>::Output> + + Allocator>::Output> +{ + // initialize the random matrix + let dim = N::try_to_usize().unwrap(); + let mut rand_mat = OMatrix::::from_fn(|j, k| { + let n = j*dim + k; + E*((n*n) as f64) % 2.0 - 1.0 + }) * (3.0 / (dim as f64)).sqrt(); + /*let mut rand_mat = OMatrix::::identity();*/ + + // initialize the rotation step + let mut rot_step = OMatrix::::identity(); + let max_freq = 4; + for n in (0..dim).step_by(2) { + let ang = PI * ((n % max_freq) as f64) / (time_res as f64); + let ang_cos = ang.cos(); + let ang_sin = ang.sin(); + rot_step[(n, n)] = ang_cos; + rot_step[(n+1, n)] = ang_sin; + rot_step[(n, n+1)] = -ang_sin; + rot_step[(n+1, n+1)] = ang_cos; + } + + // find the eigenvalues + let mut eigval_series = Vec::, N>>::with_capacity(time_res); + eigval_series.push(rand_mat.complex_eigenvalues()); + for _ in 1..time_res { + rand_mat = &rot_step * rand_mat; + eigval_series.push(rand_mat.complex_eigenvalues()); + } + eigval_series +}*/ \ No newline at end of file diff --git a/lang-trials/rust-benchmark-native/src/main.rs b/lang-trials/rust-benchmark-native/src/main.rs new file mode 100644 index 0000000..1a3a787 --- /dev/null +++ b/lang-trials/rust-benchmark-native/src/main.rs @@ -0,0 +1,110 @@ +// based on Olivier Pelhatre's GTK 3 example, ported to GTK 4 +// +// https://github.com/Ouam74/RUST_Real-time_plots_using_GTK-rs_and_Plotters-rs +// +// a self-contained component might draw on the example below, by StackOverflow +// user Nicolas +// +// https://stackoverflow.com/a/76548487 +// +// here's a crash course in `plotters` +// +// https://plotters-rs.github.io/book/basic/basic_data_plotting.html +// + +extern crate cairo; +use plotters::prelude::*; +use plotters_cairo::CairoBackend; +use gtk::{ + glib, + prelude::*, + Adjustment, + Align, + Application, + ApplicationWindow, + Box, + DrawingArea, + Label, + Orientation, + /*Picture,*/ + Scale +}; +/*use plotters_gtk4::Paintable;*/ +use std::time::Instant; + +mod engine; + +fn main() -> glib::ExitCode { + let app = Application::builder() + .application_id("org.studioinfinity.rust-benchmark-native") + .build(); + + app.connect_activate(|app| { + /* run time is typically 77 ms, but at one point i was consistently + getting more like 260 ms. it's not clear what was causing that. building + from scratch seemed to give the short run time, and waiting a while + since the last build might also have had some effect */ + const TIME_RES: usize = 100; + let start_time = Instant::now(); + let eigval_series = engine::rand_eigval_series(60, TIME_RES); + let run_time = start_time.elapsed().as_millis(); + + // application state + let time_step = Adjustment::new(0.0, 0.0, TIME_RES as f64, 1.0, 0.0, 0.0); + + // create the window. + let window = ApplicationWindow::builder() + .application(app) + .title("The circular law") + .build(); + + // create a vertical box + let container = Box::new(Orientation::Vertical, 5); + window.set_child(Some(&container)); + + // create the run time readout + let run_time_readout = Label::builder() + .margin_top(5) + .margin_start(10) + .halign(Align::Start) + .label(glib::gformat!("{} ms", run_time)) + .build(); + container.append(&run_time_readout); + + // set up the drawing area + let drawing_area = DrawingArea::builder() + .content_width(600) + .content_height(600) + .build(); + let time_step_for_draw = time_step.clone(); + let draw_eigvals = move |_: &DrawingArea, context: &cairo::Context, width: i32, height: i32| { + let root = CairoBackend::new(&context, (width as u32, height as u32)).unwrap().into_drawing_area(); + let _ = root.fill(&BLACK); + + const R_DISP: f64 = 1.5; + let mut chart = ChartBuilder::on(&root) + .build_cartesian_2d(-R_DISP..R_DISP, -R_DISP..R_DISP) + .unwrap(); + let time_step_val = (time_step_for_draw.value() as usize).min(TIME_RES-1); + let eigval_iter = eigval_series[time_step_val].iter(); + let _ = chart.draw_series( + eigval_iter.map(|z| Circle::new((z.re, z.im), 3, WHITE.filled())) + ); + let _ = root.present(); + }; + DrawingAreaExtManual::set_draw_func(&drawing_area, draw_eigvals); + container.append(&drawing_area); + + // set up the time step slider + let time_step_scale = Scale::new(Orientation::Horizontal, Some(&time_step)); + time_step_scale.connect_value_changed(move |_: &Scale| { + drawing_area.queue_draw(); + }); + container.append(&time_step_scale); + + // show the window + window.present(); + }); + + app.run() +} \ No newline at end of file From 8cb73f88d0726dd56d11bc62397d7ff0c4297a03 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Mon, 19 Aug 2024 13:12:50 -0700 Subject: [PATCH 7/7] Rust native benchmark: drop unused dependencies Also, drop the commented-out beginnings of a `plotters-gtk4` version. I can't use `plotters-gtk4` on my machine because it requires GTK 4.14 or higher, and Ubuntu 22.04 is still at GTK 4.6. --- lang-trials/rust-benchmark-native/Cargo.toml | 2 -- lang-trials/rust-benchmark-native/src/main.rs | 6 ------ 2 files changed, 8 deletions(-) diff --git a/lang-trials/rust-benchmark-native/Cargo.toml b/lang-trials/rust-benchmark-native/Cargo.toml index 0ed8747..9cc878c 100644 --- a/lang-trials/rust-benchmark-native/Cargo.toml +++ b/lang-trials/rust-benchmark-native/Cargo.toml @@ -7,11 +7,9 @@ edition = "2021" [dependencies] cairo-rs = "0.20.1" gtk = { package = "gtk4", version = "0.9.0" } -##minifb = "0.27.0" nalgebra = "0.33.0" plotters = "0.3.6" plotters-cairo = "0.7.0" -##plotters-gtk4 = { git = "https://github.com/baarkerlounger/plotters-gtk4.git", branch = "patch-1" } [profile.release] opt-level = "s" # optimize for small code size diff --git a/lang-trials/rust-benchmark-native/src/main.rs b/lang-trials/rust-benchmark-native/src/main.rs index 1a3a787..f51389d 100644 --- a/lang-trials/rust-benchmark-native/src/main.rs +++ b/lang-trials/rust-benchmark-native/src/main.rs @@ -26,10 +26,8 @@ use gtk::{ DrawingArea, Label, Orientation, - /*Picture,*/ Scale }; -/*use plotters_gtk4::Paintable;*/ use std::time::Instant; mod engine; @@ -40,10 +38,6 @@ fn main() -> glib::ExitCode { .build(); app.connect_activate(|app| { - /* run time is typically 77 ms, but at one point i was consistently - getting more like 260 ms. it's not clear what was causing that. building - from scratch seemed to give the short run time, and waiting a while - since the last build might also have had some effect */ const TIME_RES: usize = 100; let start_time = Instant::now(); let eigval_series = engine::rand_eigval_series(60, TIME_RES);