mandelbrot Rust #3 program
source code
// The Computer Language Benchmarks Game
// https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
//
// contributed by Matt Watson
// contributed by TeXitoi
extern crate futures;
extern crate futures_cpupool;
use std::io::Write;
use std::ops::{Add, Mul, Sub};
use std::sync::Arc;
use futures::Future;
use futures_cpupool::{CpuPool, CpuFuture};
const MAX_ITER: usize = 50;
const VLEN: usize = 8;
const ZEROS: Vecf64 = Vecf64([0.; VLEN]);
macro_rules! for_vec {
( in_each [ $( $val:tt ),* ] do $from:ident $op:tt $other:ident ) => {
$( $from.0[$val] $op $other.0[$val]; )*
};
( $from:ident $op:tt $other:ident ) => {
for_vec!(in_each [0, 1, 2, 3, 4, 5, 6, 7] do $from $op $other);
};
}
#[derive(Clone, Copy)]
pub struct Vecf64([f64; VLEN]);
impl Mul for Vecf64 {
type Output = Vecf64;
fn mul(mut self, other: Vecf64) -> Vecf64 {
for_vec!(self *= other);
self
}
}
impl Add for Vecf64 {
type Output = Vecf64;
fn add(mut self, other: Vecf64) -> Vecf64 {
for_vec!(self += other);
self
}
}
impl Sub for Vecf64 {
type Output = Vecf64;
fn sub(mut self, other: Vecf64) -> Vecf64 {
for_vec!(self -= other);
self
}
}
pub fn mbrot8(cr: Vecf64, ci: Vecf64) -> u8 {
let mut zr = ZEROS;
let mut zi = ZEROS;
let mut tr = ZEROS;
let mut ti = ZEROS;
for _ in 0..MAX_ITER / 5 {
for _ in 0..5 {
zi = (zr + zr) * zi + ci;
zr = tr - ti + cr;
tr = zr * zr;
ti = zi * zi;
}
if (tr + ti).0.iter().all(|&t| t > 4.) {
return 0;
}
}
(tr + ti).0.iter()
.enumerate()
.map(|(i, &t)| if t <= 4. { 0x80 >> i } else { 0 })
.fold(0, |accu, b| accu | b)
}
fn main() {
let size = std::env::args().nth(1).and_then(|n| n.parse().ok()).unwrap_or(200);
let size = size / VLEN * VLEN;
let inv = 2. / size as f64;
let mut xloc = vec![ZEROS; size / VLEN];
for i in 0..size {
xloc[i / VLEN].0[i % VLEN] = i as f64 * inv - 1.5;
}
let xloc = Arc::new(xloc);
let pool = CpuPool::new_num_cpus();
let future_rows: Vec<CpuFuture<Vec<_>, ()>> = (0..size).map(|y| {
let xloc = xloc.clone();
let ci = Vecf64([y as f64 * inv - 1.; VLEN]);
pool.spawn_fn(move || Ok((0..size / VLEN).map(|x| mbrot8(xloc[x], ci)).collect()))
}).collect();
println!("P4\n{} {}", size, size);
let stdout_unlocked = std::io::stdout();
let mut stdout = stdout_unlocked.lock();
for row in future_rows {
stdout.write_all(&row.wait().unwrap()).unwrap();
}
}
notes, command-line, and program output
NOTES:
64-bit Ubuntu quad core
rustc 1.44.0 (49cae5576 2020-06-01)
LLVM version: 9.0
Fri, 05 Jun 2020 20:31:51 GMT
MAKE:
/opt/src/rust-1.44.0/bin/rustc -C opt-level=3 -C target-cpu=core2 -C lto -C codegen-units=1 -L /opt/src/rust-libs --extern futures=/opt/src/rust-libs/libfutures-ad0a024e469c2676.rlib mandelbrot.rs -o mandelbrot.rust-3.rust_run
error[E0599]: no method named `wait` found for struct `futures_cpupool::CpuFuture<std::vec::Vec<u8>, ()>` in the current scope
--> mandelbrot.rs:96:31
|
96 | stdout.write_all(&row.wait().unwrap()).unwrap();
| ^^^^ method not found in `futures_cpupool::CpuFuture<std::vec::Vec<u8>, ()>`
|
::: /home/dunham/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-cpupool-0.1.8/src/lib.rs:129:1
|
129 | pub struct CpuFuture<T, E> {
| -------------------------- doesn't satisfy `_: futures::Future`
|
::: /home/dunham/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.29/src/future/mod.rs:297:8
|
297 | fn wait(self) -> result::Result<Self::Item, Self::Error>
| ----
| |
| the method is available for `std::boxed::Box<futures_cpupool::CpuFuture<std::vec::Vec<u8>, ()>>` here
| the method is available for `std::sync::Arc<futures_cpupool::CpuFuture<std::vec::Vec<u8>, ()>>` here
| the method is available for `std::rc::Rc<futures_cpupool::CpuFuture<std::vec::Vec<u8>, ()>>` here
|
= note: the method `wait` exists but the following trait bounds were not satisfied:
`futures_cpupool::CpuFuture<std::vec::Vec<u8>, ()>: futures::Future`
which is required by `&mut futures_cpupool::CpuFuture<std::vec::Vec<u8>, ()>: futures::Future`
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
10 | use futures::future::Future;
|
warning: unused import: `futures::Future`
--> mandelbrot.rs:13:5
|
13 | use futures::Future;
| ^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0599`.
make: [/home/dunham/8000-benchmarksgame/nanobench/makefiles/u64q.programs.Makefile:384: mandelbrot.rust-3.rust_run] Error 1 (ignored)
9.37s to complete and log all make actions
COMMAND LINE:
./mandelbrot.rust-3.rust_run 1000
MAKE ERROR