为什么我的 Rust 程序 运行 比 Java 等效程序慢两倍?
Why is my Rust program running more that twice as slow as the Java equivalent?
我有一个程序,对于小于或等于输入的所有整数,可以表示为两个立方体之和的数字,两次,也就是拉马努金数问题。
我用 Java 和 Rust 编写了这个,但是,与 Java 相比,它在 Rust 中的运行速度慢了两倍多。
我可以做些什么来让它表现得更好,或者改进它吗?
防锈代码:
use num_integer::Roots;
fn main() {
let v = 984067;
// let v = 87539319;
for i in 1..=v {
ramanujan(i)
}
}
fn ramanujan(m: i32) {
let maxcube = m.cbrt();
let mut res1 = 0;
let mut res2 = 0;
let mut _res3 = 0;
let mut _res4 = 0;
for i in 1..=maxcube {
for j in 1..=maxcube {
if i * i * i + j * j * j == m {
res1 = i;
res2 = j;
break;
}
}
}
for k in 1..=maxcube {
for l in 1..=maxcube {
if k == res1 || k == res2 || l == res1 || l == res2 {
continue;
}
if k * k * k + l * l * l == m {
_res3 = k;
_res4 = l;
break;
}
}
}
// if ((res1 * res1 * res1) + (res2 * res2 * res2) == m) && ((res3 * res3 * res3) + (res4 * res4 * res4) == m) {
// println!("{} is representable as the sums of two different sets of two cubes!\nThese values are {}, {}, and {}, {}.", m, res1, res2, res3, res4);
// }
}
Java代码:
public class Ramun {
public static void main(String[] args) {
int v = 984067;
// int v = 87539319;
for (int i = 1; i <= v; i++) {
ramanujan(i);
}
}
public static void ramanujan(int m) {
int maxcube = (int) Math.round(Math.cbrt(m));
int res1 = 0, res2 = 0, res3 = 0, res4 = 0;
for (int i = 1; i <= maxcube; i++) {
for (int j = 1; j <= maxcube; j++) {
if (((i * i * i) + (j * j * j)) == m) {
res1 = i;
res2 = j;
break;
}
}
}
for (int k = 1; k <= maxcube; k++) {
for (int l = 1; l <= maxcube; l++) {
if (k == res1 || k == res2 || l == res1 || l == res2)
continue;
if (((k * k * k) + (l * l * l)) == m) {
res3 = k;
res4 = l;
break;
}
}
}
// if (((res1 * res1 * res1) + (res2 * res2 * res2) == m) && ((res3 * res3 * res3) + (res4 * res4 * res4) == m)) {
// System.out.printf("%d is representable as the sums of two different sets of two cubes!%nThese values are %d, %d, and %d, %d.%n", m, res1, res2, res3, res4);
// }
}
}
Time output for both programs
问题出在RangeInclusive
,这可能很昂贵。
这是一个避免它的版本:
fn ramanujan(m: i32) {
let maxcube = m.cbrt() + 1; // we know it can't overflow
let mut res1 = 0;
let mut res2 = 0;
let mut res3 = 0;
let mut res4 = 0;
for i in 1..maxcube {
for j in 1..maxcube {
if i * i * i + j * j * j == m {
res1 = i;
res2 = j;
break;
}
}
}
for k in 1..maxcube {
for l in 1..maxcube {
if k == res1 || k == res2 || l == res1 || l == res2 {
continue;
}
if k * k * k + l * l * l == m {
res3 = k;
res4 = l;
break;
}
}
}
}
结果:
From: 0.01s user 0.00s system 0% cpu 17.993 total
To: 0.00s user 0.01s system 0% cpu 3.494 total
我在 #45222 中添加了评论以提请注意此问题。
看起来 for_each()
也允许更好的性能(因为 for
循环更自然并且应该具有相同的性能,它应该被视为一个错误):
fn ramanujan(m: i32) {
let maxcube = m.cbrt();
let mut res1 = 0;
let mut res2 = 0;
let mut res3 = 0;
let mut res4 = 0;
(1..=maxcube).for_each(|i| {
(1..=maxcube).try_for_each(|j| {
if i * i * i + j * j * j == m {
res1 = i;
res2 = j;
ControlFlow::Break(())
} else {
ControlFlow::Continue(())
}
});
});
(1..=maxcube).for_each(|k| {
(1..=maxcube).try_for_each(|l| {
if k != res1 && k != res2 && l != res1 && l != res2 && k * k * k + l * l * l == m {
res3 = k;
res4 = l;
ControlFlow::Break(())
} else {
ControlFlow::Continue(())
}
});
});
}
0.00s user 0.01s system 0% cpu 4.029 total
我有一个程序,对于小于或等于输入的所有整数,可以表示为两个立方体之和的数字,两次,也就是拉马努金数问题。
我用 Java 和 Rust 编写了这个,但是,与 Java 相比,它在 Rust 中的运行速度慢了两倍多。
我可以做些什么来让它表现得更好,或者改进它吗?
防锈代码:
use num_integer::Roots;
fn main() {
let v = 984067;
// let v = 87539319;
for i in 1..=v {
ramanujan(i)
}
}
fn ramanujan(m: i32) {
let maxcube = m.cbrt();
let mut res1 = 0;
let mut res2 = 0;
let mut _res3 = 0;
let mut _res4 = 0;
for i in 1..=maxcube {
for j in 1..=maxcube {
if i * i * i + j * j * j == m {
res1 = i;
res2 = j;
break;
}
}
}
for k in 1..=maxcube {
for l in 1..=maxcube {
if k == res1 || k == res2 || l == res1 || l == res2 {
continue;
}
if k * k * k + l * l * l == m {
_res3 = k;
_res4 = l;
break;
}
}
}
// if ((res1 * res1 * res1) + (res2 * res2 * res2) == m) && ((res3 * res3 * res3) + (res4 * res4 * res4) == m) {
// println!("{} is representable as the sums of two different sets of two cubes!\nThese values are {}, {}, and {}, {}.", m, res1, res2, res3, res4);
// }
}
Java代码:
public class Ramun {
public static void main(String[] args) {
int v = 984067;
// int v = 87539319;
for (int i = 1; i <= v; i++) {
ramanujan(i);
}
}
public static void ramanujan(int m) {
int maxcube = (int) Math.round(Math.cbrt(m));
int res1 = 0, res2 = 0, res3 = 0, res4 = 0;
for (int i = 1; i <= maxcube; i++) {
for (int j = 1; j <= maxcube; j++) {
if (((i * i * i) + (j * j * j)) == m) {
res1 = i;
res2 = j;
break;
}
}
}
for (int k = 1; k <= maxcube; k++) {
for (int l = 1; l <= maxcube; l++) {
if (k == res1 || k == res2 || l == res1 || l == res2)
continue;
if (((k * k * k) + (l * l * l)) == m) {
res3 = k;
res4 = l;
break;
}
}
}
// if (((res1 * res1 * res1) + (res2 * res2 * res2) == m) && ((res3 * res3 * res3) + (res4 * res4 * res4) == m)) {
// System.out.printf("%d is representable as the sums of two different sets of two cubes!%nThese values are %d, %d, and %d, %d.%n", m, res1, res2, res3, res4);
// }
}
}
Time output for both programs
问题出在RangeInclusive
,这可能很昂贵。
这是一个避免它的版本:
fn ramanujan(m: i32) {
let maxcube = m.cbrt() + 1; // we know it can't overflow
let mut res1 = 0;
let mut res2 = 0;
let mut res3 = 0;
let mut res4 = 0;
for i in 1..maxcube {
for j in 1..maxcube {
if i * i * i + j * j * j == m {
res1 = i;
res2 = j;
break;
}
}
}
for k in 1..maxcube {
for l in 1..maxcube {
if k == res1 || k == res2 || l == res1 || l == res2 {
continue;
}
if k * k * k + l * l * l == m {
res3 = k;
res4 = l;
break;
}
}
}
}
结果:
From: 0.01s user 0.00s system 0% cpu 17.993 total
To: 0.00s user 0.01s system 0% cpu 3.494 total
我在 #45222 中添加了评论以提请注意此问题。
看起来 for_each()
也允许更好的性能(因为 for
循环更自然并且应该具有相同的性能,它应该被视为一个错误):
fn ramanujan(m: i32) {
let maxcube = m.cbrt();
let mut res1 = 0;
let mut res2 = 0;
let mut res3 = 0;
let mut res4 = 0;
(1..=maxcube).for_each(|i| {
(1..=maxcube).try_for_each(|j| {
if i * i * i + j * j * j == m {
res1 = i;
res2 = j;
ControlFlow::Break(())
} else {
ControlFlow::Continue(())
}
});
});
(1..=maxcube).for_each(|k| {
(1..=maxcube).try_for_each(|l| {
if k != res1 && k != res2 && l != res1 && l != res2 && k * k * k + l * l * l == m {
res3 = k;
res4 = l;
ControlFlow::Break(())
} else {
ControlFlow::Continue(())
}
});
});
}
0.00s user 0.01s system 0% cpu 4.029 total