The Q6600
Benchmarks Game

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