]>
git.proxmox.com Git - rustc.git/blob - src/test/bench/shootout-mandelbrot.rs
1 // The Computer Language Benchmarks Game
2 // http://benchmarksgame.alioth.debian.org/
4 // contributed by the Rust Project Developers
6 // Copyright (c) 2012-2014 The Rust Project Developers
8 // All rights reserved.
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions
14 // - Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
17 // - Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in
19 // the documentation and/or other materials provided with the
22 // - Neither the name of "The Computer Language Benchmarks Game" nor
23 // the name of "The Computer Language Shootout Benchmarks" nor the
24 // names of its contributors may be used to endorse or promote
25 // products derived from this software without specific prior
26 // written permission.
28 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 // OF THE POSSIBILITY OF SUCH DAMAGE.
41 #![feature(core_simd, core)]
43 // ignore-pretty very bad with line comments
46 use std
::io
::prelude
::*;
52 const ITER
: usize = 50;
53 const LIMIT
: f64 = 2.0;
54 const WORKERS
: usize = 16;
56 fn mandelbrot
<W
: Write
>(w
: usize, mut out
: W
) -> io
::Result
<()> {
57 assert_eq
!(WORKERS
% 2, 0);
59 // Ensure w and h are multiples of 8.
60 let w
= (w
+ 7) / 8 * 8;
63 let chunk_size
= h
/ WORKERS
;
65 // Account for remainders in workload division, e.g. 1000 / 16 = 62.5
66 let last_chunk_size
= if h
% WORKERS
!= 0 {
67 chunk_size
+ h
% WORKERS
73 let inverse_w_doubled
= 2.0 / w
as f64;
74 let inverse_h_doubled
= 2.0 / h
as f64;
75 let v_inverses
= f64x2(inverse_w_doubled
, inverse_h_doubled
);
76 let v_consts
= f64x2(1.5, 1.0);
78 // A lot of this code assumes this (so do other lang benchmarks)
80 let mut precalc_r
= Vec
::with_capacity(w
);
81 let mut precalc_i
= Vec
::with_capacity(h
);
83 let precalc_futures
= (0..WORKERS
).map(|i
| {
84 thread
::spawn(move|| {
85 let mut rs
= Vec
::with_capacity(w
/ WORKERS
);
86 let mut is
= Vec
::with_capacity(w
/ WORKERS
);
88 let start
= i
* chunk_size
;
89 let end
= if i
== (WORKERS
- 1) {
90 start
+ last_chunk_size
95 // This assumes w == h
98 let xy
= f64x2(xf
, xf
);
100 let f64x2(r
, i
) = xy
* v_inverses
- v_consts
;
107 }).collect
::<Vec
<_
>>();
109 for res
in precalc_futures
{
110 let (rs
, is
) = res
.join().unwrap();
111 precalc_r
.extend(rs
);
112 precalc_i
.extend(is
);
115 assert_eq
!(precalc_r
.len(), w
);
116 assert_eq
!(precalc_i
.len(), h
);
118 let arc_init_r
= Arc
::new(precalc_r
);
119 let arc_init_i
= Arc
::new(precalc_i
);
121 let data
= (0..WORKERS
).map(|i
| {
122 let vec_init_r
= arc_init_r
.clone();
123 let vec_init_i
= arc_init_i
.clone();
125 thread
::spawn(move|| {
126 let mut res
: Vec
<u8> = Vec
::with_capacity((chunk_size
* w
) / 8);
127 let init_r_slice
= vec_init_r
;
129 let start
= i
* chunk_size
;
130 let end
= if i
== (WORKERS
- 1) {
131 start
+ last_chunk_size
136 for &init_i
in &vec_init_i
[start
..end
] {
137 write_line(init_i
, &init_r_slice
, &mut res
);
142 }).collect
::<Vec
<_
>>();
144 try
!(writeln
!(&mut out
, "P4\n{} {}", w
, h
));
146 try
!(out
.write_all(&res
.join().unwrap()));
151 fn write_line(init_i
: f64, vec_init_r
: &[f64], res
: &mut Vec
<u8>) {
152 let v_init_i
: f64x2
= f64x2(init_i
, init_i
);
153 let v_2
: f64x2
= f64x2(2.0, 2.0);
154 const LIMIT_SQUARED
: f64 = LIMIT
* LIMIT
;
156 for chunk_init_r
in vec_init_r
.chunks(8) {
157 let mut cur_byte
= 0xff;
161 let v_init_r
= f64x2(chunk_init_r
[i
], chunk_init_r
[i
+ 1]);
162 let mut cur_r
= v_init_r
;
163 let mut cur_i
= v_init_i
;
164 let mut r_sq
= v_init_r
* v_init_r
;
165 let mut i_sq
= v_init_i
* v_init_i
;
172 cur_i
= v_2
* r
* i
+ v_init_i
;
173 cur_r
= r_sq
- i_sq
+ v_init_r
;
175 let f64x2(bit1
, bit2
) = r_sq
+ i_sq
;
177 if bit1
> LIMIT_SQUARED
{
182 if bit2
> LIMIT_SQUARED
{
187 r_sq
= cur_r
* cur_r
;
188 i_sq
= cur_i
* cur_i
;
191 cur_byte
= (cur_byte
<< 2) + b
;
195 res
.push(cur_byte^
-1);
200 let mut args
= env
::args();
201 let res
= if args
.len() < 2 {
202 println
!("Test mode: do not dump the image because it's not utf8, \
203 which interferes with the test runner.");
204 mandelbrot(1000, io
::sink())
206 mandelbrot(args
.nth(1).unwrap().parse().unwrap(), io
::stdout())