在论坛里安利Rust的时候惨遭打脸 用的是这个程序:
fn calc_n(n:u64){
print!("N={},",n);
let now=std::time::Instant::now();
let mut ans=0u64;
let (mut r1,mut r2,mut r3,mut r4,mut r5,mut r6);
for a1 in 1..=n>>3{
r1=n-a1;
for a2 in a1..=r1/7{
r2=r1-a2;
for a3 in a2..=r2/6{
r3=r2-a3;
for a4 in a3..=r3/5{
r4=r3-a4;
for a5 in a4..=r4>>2{
r5=r4-a5;
for a6 in a5..=r5/3{
r6=r5-a6;
for a7 in a6..=r6>>1{
ans+=a1^a2^a3^a4^a5^a6^a7^(r6-a7);
}
}
}
}
}
}
}
println!("{}, cost={:?}",ans,now.elapsed());
}
fn main(){
calc_n(100);
calc_n(160);
calc_n(300);
calc_n(400);
calc_n(500);
calc_n(600);
}
有人给出了julia版本:
function calcN(n::Int64)
t1 = time()
ans::Int64 = 0
for a1=1:div(n, 8)
r1 = n - a1
for a2=a1:div(r1, 7)
r2 = r1 - a2
for a3=a2:div(r2, 6)
r3 = r2 - a3
for a4=a3:div(r3, 5)
r4 = r3 - a4
for a5=a4:div(r4, 4)
r5 = r4 - a5
for a6=a5:div(r5, 3)
r6 = r5 - a6
for a7=a6:div(r6, 2)
a8=r6 - a7
ans += xor(xor(xor(a1, a2), xor(a3, a4)), xor(xor(a5, a6), xor(a7, a8)))
end
end
end
end
end
end
end
println("n=$n, ans = $ans, cost = $(time() -t1)")
end
在我的笔记本(i7-8750H
, 5.8.18-1-MANJARO
)上测试,
julia
julia> calcN(100);
n=100, ans = 29892426, cost = 0.0006000995635986328
julia> calcN(160);
n=160, ans = 901994896, cost = 0.009427070617675781
julia> calcN(300);
n=300, ans = 109638857854, cost = 0.4203529357910156
julia> calcN(400);
n=400, ans = 1260273347474, cost = 2.5435290336608887
julia> calcN(500);
n=500, ans = 6722928203618, cost = 10.702456951141357
julia> calcN(600);
n=600, ans = 25125831176186, cost = 34.18349599838257
rust,使用指令rustc test.rs -O && ./test
编译&&运行
N=100,29892426, cost=1.616831ms
N=160,901994896, cost=30.246651ms
N=300,109638857854, cost=1.737976853s
N=400,1260273347474, cost=11.636545741s
N=500,6722928203618, cost=51.702947067s
N=600,25125831176186, cost=177.460155807s
想问一下rust究竟出了什么问题,导致Rust的耗时是Julia的5倍
不知哪位大神能抽空解答一下
不胜感激。
update:国外网友的尝试:
把a..=b
改成a..b+1
,会获得一个显著的提速
更多的脑洞,可以看https://users.rust-lang.org/t/a-performance-problem-compared-with-julia/51871/15
虽然目前rust还是不如julia快(有人汇报过更快的结果但是没有复现用代码)……不过已经很接近了。
我做过的尝试:
使用top,两个程序都占用100%的CPU,没有哪个偷偷开多核
输出一致,两个程序应该没有漏掉某个计算。+
跟xor
同时出现的话,编译器应该不会借助数学公式优化掉某个循环
在julia里面用ans += xor(xor(xor(a1, a2), xor(a3, a4)), xor(xor(a5, a6), xor(a7, a8)))+1
替代原计算程序,耗时略有增加,这证明了julia大概没有特别优化这几个xor判断
评论区
写评论搜别的东西不小心搜进来了,看了官方论坛帖子的solution,我只想说,局部变量牛逼!
最后结果怎么样
👇
Neutron3529: ……多谢告知
看来是我记错了。
--
👇
shaitao: 我看了 rustc --help, 怎么 -O 是 O2
-O Equivalent to -C opt-level=2
--
👇
Neutron3529: 关于优化等级,rustc里面-O就是O3啊
以及,就算println宏再耗时……每次调用函数只执行一次
println!
啊,总不能一次println!
花好几秒吧……--
👇
tian-deng: 首先应该是编译器优化的等级不一样, 其次就是rust的println宏相比较计算更耗费性能, 做了很多复杂的工作.
……多谢告知
看来是我记错了。
--
👇
shaitao: 我看了 rustc --help, 怎么 -O 是 O2
-O Equivalent to -C opt-level=2
--
👇
Neutron3529: 关于优化等级,rustc里面-O就是O3啊
以及,就算println宏再耗时……每次调用函数只执行一次
println!
啊,总不能一次println!
花好几秒吧……--
👇
tian-deng: 首先应该是编译器优化的等级不一样, 其次就是rust的println宏相比较计算更耗费性能, 做了很多复杂的工作.
我看了 rustc --help, 怎么 -O 是 O2
-O Equivalent to -C opt-level=2
--
👇
Neutron3529: 关于优化等级,rustc里面-O就是O3啊
以及,就算println宏再耗时……每次调用函数只执行一次
println!
啊,总不能一次println!
花好几秒吧……--
👇
tian-deng: 首先应该是编译器优化的等级不一样, 其次就是rust的println宏相比较计算更耗费性能, 做了很多复杂的工作.
照着那个帖子,测试了最内的两层for成for_each的代码,加上avx2加速后,和julia性能差不多
关于优化等级,rustc里面-O就是O3啊
以及,就算println宏再耗时……每次调用函数只执行一次
println!
啊,总不能一次println!
花好几秒吧……--
👇
tian-deng: 首先应该是编译器优化的等级不一样, 其次就是rust的println宏相比较计算更耗费性能, 做了很多复杂的工作.
首先应该是编译器优化的等级不一样, 其次就是rust的println宏相比较计算更耗费性能, 做了很多复杂的工作.
马克流明,关注后续。
mark,关注一下后续。
https://users.rust-lang.org/t/a-performance-problem-compared-with-julia/51871/3
even with -C target-feature=+avx2,+fma, the cost of Rust keeps the same.
👇
dollarkillerx: 你这没有开编译器优化把
👇
shaitao: rustc -C opt-level=3 --target-cpus 试试呢
https://rust-lang.github.io/packed_simd/perf-guide/target-feature/rustflags.html
可以看看这个~
你这没有开编译器优化把
rustc -C opt-level=3 --target-cpus 试试呢
发现一个BUG
以
n=600
为例就算avx2产生了4倍加速
把这个4倍加速去掉,32*4仍然小于177s
我用
保证了Julia只能按照64bit算接下来的运算
总不能是我的8750H下载了intel的微码无师自通AVX512(于是获得8倍提速)了吧……
--
👇
gwy15: 看了下 julia 编译出来的代码,用了大量高级指令集的指令
作为对比, rust 编译出来的结果并没有用到啥高级指令集,基本上全是 AMD64 指令集,慢是正常的。
具体我也不知道怎么让 rust 强行使用高级指令集 = =
感谢回复
明明两边都是输出llvm中间码……
不由得想起之前发现rust
f64/f64
比i32/i32
还快的情况了……--
👇
gwy15: 看了下 julia 编译出来的代码,用了大量高级指令集的指令
作为对比, rust 编译出来的结果并没有用到啥高级指令集,基本上全是 AMD64 指令集,慢是正常的。
具体我也不知道怎么让 rust 强行使用高级指令集 = =
看了下 julia 编译出来的代码,用了大量高级指令集的指令
作为对比, rust 编译出来的结果并没有用到啥高级指令集,基本上全是 AMD64 指令集,慢是正常的。
具体我也不知道怎么让 rust 强行使用高级指令集 = =