rust 为什么range / loop比java慢?

lx0bsm1f  于 2023-01-30  发布在  Java
关注(0)|答案(1)|浏览(194)

我有一个程序,对于所有小于或等于输入值的整数,它可以找到可以表示为两个立方体之和的数字,两次,也就是Ramanujan的数字问题。
我已经用Java和Rust编写了这篇文章,但是,与Java相比,它在Rust中运行的速度慢了两倍多。
我能做些什么来使它表现得更好,或者改进它吗?
rust eclipse 代码:

  1. use num_integer::Roots;
  2. fn main() {
  3. let v = 984067;
  4. // let v = 87539319;
  5. for i in 1..=v {
  6. ramanujan(i)
  7. }
  8. }
  9. fn ramanujan(m: i32) {
  10. let maxcube = m.cbrt();
  11. let mut res1 = 0;
  12. let mut res2 = 0;
  13. let mut _res3 = 0;
  14. let mut _res4 = 0;
  15. for i in 1..=maxcube {
  16. for j in 1..=maxcube {
  17. if i * i * i + j * j * j == m {
  18. res1 = i;
  19. res2 = j;
  20. break;
  21. }
  22. }
  23. }
  24. for k in 1..=maxcube {
  25. for l in 1..=maxcube {
  26. if k == res1 || k == res2 || l == res1 || l == res2 {
  27. continue;
  28. }
  29. if k * k * k + l * l * l == m {
  30. _res3 = k;
  31. _res4 = l;
  32. break;
  33. }
  34. }
  35. }
  36. // if ((res1 * res1 * res1) + (res2 * res2 * res2) == m) && ((res3 * res3 * res3) + (res4 * res4 * res4) == m) {
  37. // println!("{} is representable as the sums of two different sets of two cubes!\nThese values are {}, {}, and {}, {}.", m, res1, res2, res3, res4);
  38. // }
  39. }

Java代码:

  1. public class Ramun {
  2. public static void main(String[] args) {
  3. int v = 984067;
  4. // int v = 87539319;
  5. for (int i = 1; i <= v; i++) {
  6. ramanujan(i);
  7. }
  8. }
  9. public static void ramanujan(int m) {
  10. int maxcube = (int) Math.round(Math.cbrt(m));
  11. int res1 = 0, res2 = 0, res3 = 0, res4 = 0;
  12. for (int i = 1; i <= maxcube; i++) {
  13. for (int j = 1; j <= maxcube; j++) {
  14. if (((i * i * i) + (j * j * j)) == m) {
  15. res1 = i;
  16. res2 = j;
  17. break;
  18. }
  19. }
  20. }
  21. for (int k = 1; k <= maxcube; k++) {
  22. for (int l = 1; l <= maxcube; l++) {
  23. if (k == res1 || k == res2 || l == res1 || l == res2)
  24. continue;
  25. if (((k * k * k) + (l * l * l)) == m) {
  26. res3 = k;
  27. res4 = l;
  28. break;
  29. }
  30. }
  31. }
  32. // if (((res1 * res1 * res1) + (res2 * res2 * res2) == m) && ((res3 * res3 * res3) + (res4 * res4 * res4) == m)) {
  33. // 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);
  34. // }
  35. }
  36. }

Time output for both programs

6kkfgxo0

6kkfgxo01#

问题在于RangeInclusive,它可能很昂贵。
下面是一个避免这种情况的版本:

  1. fn ramanujan(m: i32) {
  2. let maxcube = m.cbrt() + 1; // we know it can't overflow
  3. let mut res1 = 0;
  4. let mut res2 = 0;
  5. let mut res3 = 0;
  6. let mut res4 = 0;
  7. for i in 1..maxcube {
  8. for j in 1..maxcube {
  9. if i * i * i + j * j * j == m {
  10. res1 = i;
  11. res2 = j;
  12. break;
  13. }
  14. }
  15. }
  16. for k in 1..maxcube {
  17. for l in 1..maxcube {
  18. if k == res1 || k == res2 || l == res1 || l == res2 {
  19. continue;
  20. }
  21. if k * k * k + l * l * l == m {
  22. res3 = k;
  23. res4 = l;
  24. break;
  25. }
  26. }
  27. }
  28. }

结果:

  1. From: 0.01s user 0.00s system 0% cpu 17.993 total
  2. To: 0.00s user 0.01s system 0% cpu 3.494 total

我在#45222中添加了一条注解,以引起对此问题的注意。
看起来for_each()也允许更好的性能(因为for循环更自然,应该具有相同的性能,应该将其视为一个bug):
一个二个一个一个

展开查看全部

相关问题