Compare commits

..

No commits in common. 'main' and 'v0.2.0' have entirely different histories.
main ... v0.2.0

  1. 1
      .gitignore
  2. 2
      Cargo.lock
  3. 2
      Cargo.toml
  4. 21
      README.md
  5. 53
      src/main.rs

1
.gitignore vendored

@ -2,4 +2,3 @@
/.idea /.idea
/release /release
mandelplot mandelplot
mandelbrot.png

2
Cargo.lock generated

@ -223,7 +223,7 @@ checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
[[package]] [[package]]
name = "mandelplot" name = "mandelplot"
version = "0.3.0" version = "0.2.0"
dependencies = [ dependencies = [
"clap", "clap",
"image", "image",

2
Cargo.toml

@ -1,6 +1,6 @@
[package] [package]
name = "mandelplot" name = "mandelplot"
version = "0.3.0" version = "0.2.0"
license = "MIT" license = "MIT"
edition = "2021" edition = "2021"
authors = ["Unbewohnte <me@unbewohnte.xyz>"] authors = ["Unbewohnte <me@unbewohnte.xyz>"]

21
README.md

@ -18,29 +18,16 @@ OPTIONS:
- `-V, --version` => Print version information - `-V, --version` => Print version information
- `-z --m_set_dimensions <m_set_dimensions>` => Set real and imaginary constraints (real_start,imaginary_startxreal_end,imaginary_end) [default: -2.5,-2.0x1.5,2.0]
## Naive benchmarks ## Naive benchmarks
Singe-threaded (19200x10800) (pre v0.2.0) Singe-threaded (19200x10800) (pre v0.2.0)
- ./mandelplot -d 19200x10800 -p dark 70.06s user 0.14s system 99% cpu 1:10.24 total
`./mandelplot -d 19200x10800 -p dark 70.06s user 0.14s system 99% cpu 1:10.24 total`
Multi-threaded (19200x10800) (v0.2.0) Multi-threaded (19200x10800) (v0.2.0)
- ./target/release/mandelplot -d 19200x10800 -p dark 85.28s user 8.06s system 258% cpu 36.079 total
`./target/release/mandelplot -d 19200x10800 -p dark 85.28s user 8.06s system 258% cpu 36.079 total` 1:10 - 0:36 == 0:34 seconds saved
1:10 - 0:36 == 0:34 saved
Multi-threaded (19200x10800) (v0.3.0)
`./mandelplot -d 19200x10800 87.43s user 10.93s system 349% cpu 28.134 total`
1:10 - 0:28 == 0:42 saved
## Interesting "places"
- `./mandelplot -z='-0.55,-0.55x-0.5,-0.48' -i 5000`
- `./mandelplot -z='-0.565,-0.565x-0.550,-0.550' -i 10000`
## TODO: ## TODO:
- ~~generate image in parallel~~ - ~~generate image in parallel~~
- ~~zooming in~~ - zooming in

53
src/main.rs

@ -28,13 +28,12 @@ use num::Complex;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
/// z(n) = z(n-1)^2 + c /// z(n) = z(n-1)^2 + c
/// Returns amount of iterations that were necessary to decide that z escapes to infinity. /// Returns amount of iterations to decide that z will escape to infinity
/// Returns None if z doesn`t escape to infinity even after specified number of iterations
fn mandelbrot(c: num::Complex<f64>, iterations: u32) -> Option<u32> { fn mandelbrot(c: num::Complex<f64>, iterations: u32) -> Option<u32> {
let mut z: Complex<f64> = num::Complex::new(0.0, 0.0); let mut z: Complex<f64> = num::Complex::new(0.0, 0.0);
for n in 0..iterations { for i in 0..iterations {
if z.norm_sqr() > 4.0 { if z.norm_sqr() > 4.0 {
return Some(n); return Some(i);
} }
z = z * z + c; z = z * z + c;
} }
@ -70,10 +69,10 @@ fn compute_pixel_color(c: num::Complex<f64>, max_iter: u32, palette: u8) -> u8 {
} }
fn main() { fn main() {
let mut re_start: f64 = -2.5; const RE_START: f64 = -2.5;
let mut re_end: f64 = 1.5; const RE_END: f64 = 1.5;
let mut im_start: f64 = -2.0; const IM_START: f64 = -2.0;
let mut im_end: f64 = 2.0; const IM_END: f64 = 2.0;
let mut width: u32 = 7680; let mut width: u32 = 7680;
let mut height: u32 = 4320; let mut height: u32 = 4320;
@ -82,7 +81,7 @@ fn main() {
let mut palette: u8 = 0; let mut palette: u8 = 0;
let matches = clap::App::new("mandelplot") let matches = clap::App::new("mandelplot")
.version("0.3.0") .version("0.2.0")
.author("Kasyanov Nikolay Alexeyevich (Unbewohnte)") .author("Kasyanov Nikolay Alexeyevich (Unbewohnte)")
.arg( .arg(
Arg::new("max_iter") Arg::new("max_iter")
@ -120,15 +119,6 @@ fn main() {
.long("palette") .long("palette")
.short('p') .short('p')
) )
.arg(
Arg::new("m_set_dimensions")
.help("Set real and imaginary constraints (real_start,imaginary_startxreal_end,imaginary_end)")
.takes_value(true)
.required(false)
.default_value("-2.5,-2.0x1.5,2.0")
.long("m_set_dimensions")
.short('z')
)
.get_matches(); .get_matches();
// process given options // process given options
@ -162,34 +152,11 @@ fn main() {
} }
} }
if let Some(arg_m_set_dimensions) = matches.value_of("m_set_dimensions") {
match arg_m_set_dimensions.split_once("x") {
Some((start, end)) => {
match start.split_once(",") {
Some((real_start, imaginary_start)) => {
re_start = real_start.parse::<f64>().unwrap();
im_start = imaginary_start.parse::<f64>().unwrap();
}
None => {}
}
match end.split_once(",") {
Some((real_end, imaginary_end)) => {
re_end = real_end.parse::<f64>().unwrap();
im_end = imaginary_end.parse::<f64>().unwrap();
}
None => {}
}
}
None => {}
}
}
let img = Arc::new(Mutex::new(RgbImage::new(width, height))); let img = Arc::new(Mutex::new(RgbImage::new(width, height)));
// run the algorithm in a naive multi-threaded way // run the algorithm in a naive multi-threaded way
const AMOUNT_OF_THREADS: usize = 24; const AMOUNT_OF_THREADS: usize = 8;
let thread_work = (height as f32 / AMOUNT_OF_THREADS as f32) as u32; let thread_work = (height as f32 / AMOUNT_OF_THREADS as f32) as u32;
let mut threads = Vec::with_capacity(AMOUNT_OF_THREADS); let mut threads = Vec::with_capacity(AMOUNT_OF_THREADS);
@ -199,7 +166,7 @@ fn main() {
threads.push(std::thread::spawn(move || { threads.push(std::thread::spawn(move || {
for y in from..from+thread_work { for y in from..from+thread_work {
for x in 0..width { for x in 0..width {
let c = pixel_to_set_point(x, y, width, height, re_start, re_end, im_start, im_end); let c = pixel_to_set_point(x, y, width, height, RE_START, RE_END, IM_START, IM_END);
let pixel_color = compute_pixel_color(c, max_iter, palette); let pixel_color = compute_pixel_color(c, max_iter, palette);
img_copy.lock().unwrap().put_pixel(x, y, Rgb([pixel_color, pixel_color, pixel_color])); img_copy.lock().unwrap().put_pixel(x, y, Rgb([pixel_color, pixel_color, pixel_color]));

Loading…
Cancel
Save