Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
b9e4fcbf
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b9e4fcbf
编写于
5月 14, 2014
作者:
K
Kevin Butler
提交者:
Alex Crichton
5月 15, 2014
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
shootout-mandelbrot: Precalc initial values & use SIMD in the main loop. +80-100%
上级
03f48534
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
125 addition
and
61 deletion
+125
-61
src/test/bench/shootout-mandelbrot.rs
src/test/bench/shootout-mandelbrot.rs
+125
-61
未找到文件。
src/test/bench/shootout-mandelbrot.rs
浏览文件 @
b9e4fcbf
...
...
@@ -8,104 +8,168 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(macro_rules)]
#![feature(simd)]
#![allow(experimental)]
// ignore-pretty very bad with line comments
extern
crate
sync
;
use
std
::
io
;
use
std
::
os
;
use
std
::
unstable
::
simd
::
f64x2
;
use
sync
::
Future
;
use
sync
::
Arc
;
static
ITER
:
int
=
50
;
static
LIMIT
:
f64
=
2.0
;
static
WORKERS
:
uint
=
16
;
macro_rules!
core_loop
(
(
$pow:expr
~
$mask:expr
:
$ctx:ident
,
$b:ident
)
=>
(
{
let
r
=
$ctx
.r
;
let
i
=
$ctx
.i
;
#[inline(always)]
fn
mandelbrot
<
W
:
io
::
Writer
>
(
w
:
uint
,
mut
out
:
W
)
->
io
::
IoResult
<
()
>
{
assert
!
(
WORKERS
%
2
==
0
);
$ctx
.r
=
r
*
r
-
i
*
i
+
$ctx
.init_r
;
$ctx
.i
=
2.0
*
r
*
i
+
$ctx
.init_i
;
// Ensure w and h are multiples of 8.
let
w
=
(
w
+
7
)
/
8
*
8
;
let
h
=
w
;
let
chunk_size
=
h
/
WORKERS
;
if
r
*
r
+
i
*
i
>
LIMIT
*
LIMIT
{
$b
|
=
$pow
;
if
$b
==
$mask
{
break
;
}
// Account for remainders in workload division, e.g. 1000 / 16 = 62.5
let
first_chunk_size
=
if
h
%
WORKERS
!=
0
{
chunk_size
+
h
%
WORKERS
}
else
{
chunk_size
};
// precalc values
let
inverse_w_doubled
=
2.0
/
w
as
f64
;
let
inverse_h_doubled
=
2.0
/
h
as
f64
;
let
v_inverses
=
f64x2
(
inverse_w_doubled
,
inverse_h_doubled
);
let
v_consts
=
f64x2
(
1.5
,
1.0
);
// A lot of this code assumes this (so do other lang benchmarks)
assert
!
(
w
==
h
);
let
mut
precalc_r
=
Vec
::
with_capacity
(
w
);
let
mut
precalc_i
=
Vec
::
with_capacity
(
h
);
let
precalc_futures
=
Vec
::
from_fn
(
WORKERS
,
|
i
|
{
Future
::
spawn
(
proc
()
{
let
mut
rs
=
Vec
::
with_capacity
(
w
/
WORKERS
);
let
mut
is
=
Vec
::
with_capacity
(
w
/
WORKERS
);
let
start
=
i
*
chunk_size
;
let
end
=
if
i
==
0
{
first_chunk_size
}
else
{
(
i
+
1
)
*
chunk_size
};
// This assumes w == h
for
x
in
range
(
start
,
end
)
{
let
xf
=
x
as
f64
;
let
xy
=
f64x2
(
xf
,
xf
);
let
f64x2
(
r
,
i
)
=
xy
*
v_inverses
-
v_consts
;
rs
.push
(
r
);
is
.push
(
i
);
}
}
);
)
#[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
}
}
(
rs
,
is
)
})
});
for
res
in
precalc_futures
.move_iter
()
{
let
(
rs
,
is
)
=
res
.unwrap
();
precalc_r
.push_all_move
(
rs
);
precalc_i
.push_all_move
(
is
);
}
assert_eq!
(
precalc_r
.len
(),
w
);
assert_eq!
(
precalc_i
.len
(),
h
);
let
arc_init_r
=
Arc
::
new
(
precalc_r
);
let
arc_init_i
=
Arc
::
new
(
precalc_i
);
let
data
=
Vec
::
from_fn
(
WORKERS
,
|
i
|
{
let
vec_init_r
=
arc_init_r
.clone
();
let
vec_init_i
=
arc_init_i
.clone
();
Future
::
spawn
(
proc
()
{
let
mut
res
:
Vec
<
u8
>
=
Vec
::
with_capacity
((
chunk_size
*
w
)
/
8
);
let
init_r_slice
=
vec_init_r
.as_slice
();
for
&
init_i
in
vec_init_i
.slice
(
i
*
chunk_size
,
(
i
+
1
)
*
chunk_size
)
.iter
()
{
write_line
(
init_i
,
init_r_slice
,
&
mut
res
);
}
res
})
});
try!
(
writeln!
(
&
mut
out
as
&
mut
Writer
,
"P4
\n
{} {}"
,
w
,
h
));
for
res
in
data
.move_iter
()
{
try!
(
out
.write
(
res
.unwrap
()
.as_slice
()));
}
out
.flush
()
}
fn
write_line
(
init_i
:
f64
,
vec_init_r
:
&
[
f64
],
res
:
&
mut
Vec
<
u8
>
)
{
let
v_init_i
:
f64x2
=
f64x2
(
init_i
,
init_i
);
let
v_2
:
f64x2
=
f64x2
(
2.0
,
2.0
);
static
LIMIT_SQUARED
:
f64
=
LIMIT
*
LIMIT
;
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
)
{
cur_byte
=
0xff
;
i
=
0
;
let
mut
cur_byte
=
0xff
;
let
mut
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
]);
let
v_init_r
=
f64x2
(
chunk_init_r
[
i
],
chunk_init_r
[
i
+
1
]);
let
mut
cur_r
=
v_init_r
;
let
mut
cur_i
=
v_init_i
;
let
mut
r_sq
=
v_init_r
*
v_init_r
;
let
mut
i_sq
=
v_init_i
*
v_init_i
;
b
=
0
;
let
mut
b
=
0
;
for
_
in
range
(
0
,
ITER
)
{
core_loop!
(
2
~
3
:
bit_1
,
b
);
core_loop!
(
1
~
3
:
bit_2
,
b
);
let
r
=
cur_r
;
let
i
=
cur_i
;
cur_i
=
v_2
*
r
*
i
+
v_init_i
;
cur_r
=
r_sq
-
i_sq
+
v_init_r
;
let
f64x2
(
bit1
,
bit2
)
=
r_sq
+
i_sq
;
if
bit1
>
LIMIT_SQUARED
{
b
|
=
2
;
if
b
==
3
{
break
;
}
}
if
bit2
>
LIMIT_SQUARED
{
b
|
=
1
;
if
b
==
3
{
break
;
}
}
r_sq
=
cur_r
*
cur_r
;
i_sq
=
cur_i
*
cur_i
;
}
cur_byte
=
(
cur_byte
<<
2
)
+
b
;
i
+=
2
;
}
res
.push
(
cur_byte
^-
1
);
}
}
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
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
,
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
=
(
y
as
f64
)
*
inverse_h_doubled
-
1.0
;
write_line
(
init_i
,
vec_init_r
.as_slice
(),
&
mut
res
);
}
res
}))
.collect
();
try!
(
writeln!
(
&
mut
out
as
&
mut
Writer
,
"P4
\n
{} {}"
,
w
,
h
));
for
res
in
data
.move_iter
()
{
try!
(
out
.write
(
res
.unwrap
()
.as_slice
()));
res
.push
(
cur_byte
^-
1
);
}
out
.flush
()
}
fn
main
()
{
let
args
=
std
::
os
::
args
();
let
args
=
os
::
args
();
let
args
=
args
.as_slice
();
let
res
=
if
args
.len
()
<
2
{
println!
(
"Test mode: do not dump the image because it's not utf8,
\
which interferes with the test runner."
);
mandelbrot
(
1000
,
std
::
io
::
util
::
NullWriter
)
mandelbrot
(
1000
,
io
::
util
::
NullWriter
)
}
else
{
mandelbrot
(
from_str
(
args
[
1
])
.unwrap
(),
std
::
io
::
stdout
())
mandelbrot
(
from_str
(
args
[
1
])
.unwrap
(),
io
::
stdout
())
};
res
.unwrap
();
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录