diff options
| author | Kevin Butler <haqkrs@gmail.com> | 2014-05-13 21:15:11 +0100 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-05-15 13:50:39 -0700 |
| commit | 03f48534b3ac38bc3792019cdd2b8a24eaebee50 (patch) | |
| tree | 56135a5eb6547772d7a1b8d13bd8b0d96cf28acc /src | |
| parent | a7bee7b05d59467bc6304b32eb14e617c2efbfc9 (diff) | |
| download | rust-03f48534b3ac38bc3792019cdd2b8a24eaebee50.tar.gz rust-03f48534b3ac38bc3792019cdd2b8a24eaebee50.zip | |
shootout-mandlebrot: calculate two bits of the result per inner loop, +10-15%
Diffstat (limited to 'src')
| -rw-r--r-- | src/test/bench/shootout-mandelbrot.rs | 72 |
1 files changed, 52 insertions, 20 deletions
diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index e17324ee596..5302bd1dd63 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -7,6 +7,7 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(macro_rules)] // ignore-pretty very bad with line comments @@ -18,27 +19,56 @@ use sync::Future; static ITER: int = 50; static LIMIT: f64 = 2.0; +macro_rules! core_loop( + ($pow:expr ~ $mask:expr: $ctx:ident, $b:ident) => ( + { + let r = $ctx.r; + let i = $ctx.i; + + $ctx.r = r * r - i * i + $ctx.init_r; + $ctx.i = 2.0 * r * i + $ctx.init_i; + + if r * r + i * i > LIMIT * LIMIT { + $b |= $pow; + if $b == $mask { break; } + } + } + ); +) + +#[inline(always)] fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) { + struct Context { r: f64, i: f64, init_i: f64, init_r: f64 } + impl Context { + #[inline(always)] + fn new(i: f64, r: f64) -> Context { + Context { r: r, i: i, init_r: r, init_i: i } + } + } + + let mut cur_byte; + let mut i; + let mut bit_1; + let mut bit_2; + let mut b; for chunk_init_r in vec_init_r.chunks(8) { - let mut cur_byte = 0xff; - let mut cur_bitmask = 0x80; - for &init_r in chunk_init_r.iter() { - let mut cur_r = init_r; - let mut cur_i = init_i; + cur_byte = 0xff; + i = 0; + + while i < 8 { + bit_1 = Context::new(init_i, chunk_init_r[i]); + bit_2 = Context::new(init_i, chunk_init_r[i + 1]); + + b = 0; for _ in range(0, ITER) { - let r = cur_r; - let i = cur_i; - cur_r = r * r - i * i + init_r; - cur_i = 2.0 * r * i + init_i; - - if r * r + i * i > LIMIT * LIMIT { - cur_byte &= !cur_bitmask; - break; - } + core_loop!(2 ~ 3: bit_1, b); + core_loop!(1 ~ 3: bit_2, b); } - cur_bitmask >>= 1; + + cur_byte = (cur_byte << 2) + b; + i += 2; } - res.push(cur_byte); + res.push(cur_byte^-1); } } @@ -46,13 +76,15 @@ fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> { // Ensure w and h are multiples of 8. let w = (w + 7) / 8 * 8; let h = w; - let chunk_size = h / 8; + let inverse_w_doubled = 2.0 / w as f64; + let inverse_h_doubled = 2.0 / h as f64; + let chunk_size = h / 16; - let data: Vec<Future<Vec<u8>>> = range(0u, 8).map(|i| Future::spawn(proc () { - let vec_init_r = Vec::from_fn(w, |x| 2.0 * (x as f64) / (w as f64) - 1.5); + let data: Vec<Future<Vec<u8>>> = range(0u, 16).map(|i| Future::spawn(proc () { + let vec_init_r = Vec::from_fn(w, |x| (x as f64) * inverse_w_doubled - 1.5); let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8); for y in range(i * chunk_size, (i + 1) * chunk_size) { - let init_i = 2.0 * (y as f64) / (h as f64) - 1.0; + let init_i = (y as f64) * inverse_h_doubled - 1.0; write_line(init_i, vec_init_r.as_slice(), &mut res); } res |
