Java与C++在简单for循环上的速度对比

huangapple go评论97阅读模式
英文:

Java vs C++ speed on simple for loop

问题

  1. #include <iostream>
  2. #include <ctime>
  3. int main()
  4. {
  5. long long x = 0;
  6. clock_t begin = clock();
  7. for (long long i = 0; i < 2147483647; i++)
  8. x += i;
  9. clock_t end = clock();
  10. double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
  11. std::cout << "Time elapsed: " << elapsed_secs << std::endl;
  12. std::cout << "x = " << x << std::endl;
  13. return 0;
  14. }
英文:

Why in simple for loop the same code in Java works 4 times faster than in C++? i.e. in Java this code completes in 700-800 ms and in C++ 4-5 SECONDS. Although C++ usually considered much faster than Java, especially with CPU-bound workloads. Have i lost sight of some important moment ???

Java:

  1. import java.time.Duration;
  2. import java.time.Instant;
  3. public class Main {
  4. public static void main(String[] args) {
  5. long x = 0;
  6. Instant start = Instant.now();
  7. for (long i = 0; i &lt; 2147483647; i++)
  8. x += i;
  9. Instant end = Instant.now();
  10. Duration result = Duration.between(start, end);
  11. System.out.println(&quot;TIME: &quot; + result.toMillis());
  12. System.out.println(&quot;X = &quot; + x);
  13. }
  14. }

Output:

  1. TIME: 799
  2. X = 2305843005992468481

C++:

  1. #include &lt;iostream&gt;
  2. #include &lt;ctime&gt;
  3. int main()
  4. {
  5. long long x = 0;
  6. clock_t begin = clock();
  7. for (long long i = 0; i &lt; 2147483647; i++)
  8. x += i;
  9. clock_t end = clock();
  10. double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
  11. std::cout &lt;&lt; &quot;Time elapsed: &quot; &lt;&lt; elapsed_secs &lt;&lt; std::endl;
  12. std::cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; std::endl;
  13. return 0;
  14. }

Output:

  1. Time elapsed: 4.59629
  2. x = 2305843005992468481

答案1

得分: 5

  1. C++在开启优化时可以运行得很快。默认情况下,编译时不会进行优化,因为编译C++需要时间。你需要使用`-O`标志,`-O2`应该是可以的。
  2. 你测量的循环是一种常见的模式,并且有一个直接的解决方案:
  3. int sum = 0;
  4. for (int i = 0; i < n; ++i)
  5. sum += i;
  6. // 这将得到相同的结果:
  7. sum = ((n+1) * n) / 2;
  8. 而且编译器知道这个技巧(它们可能不使用那个公式,因为对于`(n+1)*n`,可能会溢出,而最终结果不会溢出)。对于gcc,下面的代码:
  9. #include <iostream>
  10. int main(){
  11. long long x = 0;
  12. for (long long i = 0; i < 2147483647; ++i)
  13. x += i;
  14. std::cout << x;
  15. }
  16. [翻译为](https://godbolt.org/z/EWE4rx):
  17. main:
  18. sub rsp, 8
  19. mov edi, OFFSET FLAT:_ZSt4cout
  20. movabs rsi, 2305843005992468481
  21. call std::basic_ostream<char, std::char_traits<char> > & std::basic_ostream<char, std::char_traits<char> >::_M_insert<long long>(long long)
  22. xor eax, eax
  23. add rsp, 8
  24. ret
  25. _GLOBAL__sub_I_main:
  26. sub rsp, 8
  27. mov edi, OFFSET FLAT:_ZStL8__ioinit
  28. call std::ios_base::Init::Init() [complete object constructor]
  29. mov edx, OFFSET FLAT:__dso_handle
  30. mov esi, OFFSET FLAT:_ZStL8__ioinit
  31. mov edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
  32. add rsp, 8
  33. jmp __cxa_atexit
  34. 注意,这里没有循环!不像这样的情况需要几秒钟才能执行。
  35. 在这里查看当你关闭优化(默认情况)时会发生什么:https://godbolt.org/z/8KncEj
英文:

C++ can be fast when you turn on optimizations. The default is compiling without optimizations because compiling C++ takes time. You need to use the -O flag, -O2 should be ok.

The loop you measure is a common pattern and has a direct solution:

  1. int sum = 0;
  2. for (int i=0;i &lt; n; ++i) sum += i
  3. // this will give the same result:
  4. sum = ((n+1)*n)/2;

And compilers know about this trick (they probably don't use that formula, because it can overflow for (n+1)*n while the final result is no overflow). With gcc, this:

  1. #include &lt;iostream&gt;
  2. int main(){
  3. long long x = 0;
  4. for (long long i = 0; i &lt; 2147483647; ++i)
  5. x += i;
  6. std::cout &lt;&lt; x;
  7. }

translates to:

  1. main:
  2. sub rsp, 8
  3. mov edi, OFFSET FLAT:_ZSt4cout
  4. movabs rsi, 2305843005992468481
  5. call std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;&amp; std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;::_M_insert&lt;long long&gt;(long long)
  6. xor eax, eax
  7. add rsp, 8
  8. ret
  9. _GLOBAL__sub_I_main:
  10. sub rsp, 8
  11. mov edi, OFFSET FLAT:_ZStL8__ioinit
  12. call std::ios_base::Init::Init() [complete object constructor]
  13. mov edx, OFFSET FLAT:__dso_handle
  14. mov esi, OFFSET FLAT:_ZStL8__ioinit
  15. mov edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
  16. add rsp, 8
  17. jmp __cxa_atexit

Note that there is no loop! Unlikely this takes seconds to execute.

See here what happens when you turn off optimiziations (the default): https://godbolt.org/z/8KncEj

huangapple
  • 本文由 发表于 2020年10月14日 15:56:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/64348944.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定