What Is Wrong ?

Just starting out in C++. Why is my code so slow ? The nested loops below I think would take a day to complete while the same code in Java completes in a few seconds. I tried it in CodeBlocks using different variants of C++ and in Visual Studio for C++. This can't be right. What am I doing wrong?

1
2
3
4
5
6
7
8
9
10
11
  int a,b,c,x=0;

	for (a = 0; a < 32768; a++) {
		for (b = 0; b < 32768; b++) {
			for (c = 0; c < 32768; c++) {
				//x++;
			}
		}
		printf("a=%d\n", a);
	}
	printf("x=%d\n",x);
By default, most compilers will just give you what you asked for. If you want a billion iterations of nothing, then that's what you get.

If you turn on the optimiser however, then your b/c loops are eliminated because there is no observable side effect - aside from the time it takes to run them of course.
1
2
3
4
5
6
7
8
9
10
11
12
$ gcc -O2 bar.c
$ ./a.out | tail
a=32759
a=32760
a=32761
a=32762
a=32763
a=32764
a=32765
a=32766
a=32767
x=0


Java most likely aggressively removes redundant code.

Avoid undefined behaviour (signed integer overflow) and if it hasn't been done, enable optimisation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <cstdio>

int main()
{
    long long x = 0 ; // long long, x may be incremented beyond the largest value that an int can hold 

	for ( int a = 0; a < 32768; a++) {
		for ( int b = 0; b < 32768; b++) {
			for ( int c = 0; c < 32768; c++) {
				++x ;
			}
		}
	}
	
	std::printf( "x == %lld, expected: %lld\n", x, 32768LL*32768*32768 ) ;    
}

echo && g++ -std=c++17 -O3 -march=native -Wall -Wextra -pedantic-errors main.cpp && time ./a.out 
echo -e '\n\n==============\n\n'
echo && clang++ -std=c++17 -stdlib=libc++ -O3 -march=native -Wall -Wextra -pedantic-errors main.cpp -lsupc++ && time ./a.out

x == 35184372088832, expected: 35184372088832

real	0m0.008s
user	0m0.004s
sys	0m0.000s


==============



x == 35184372088832, expected: 35184372088832

real	0m0.007s
user	0m0.004s
sys	0m0.000s

http://coliru.stacked-crooked.com/a/afe7ce8f56d3f012
The as-if rule allows the optimiser to rewrite the code in any way as long as it does not change the observable behaviour of the program.
https://en.cppreference.com/w/cpp/language/as_if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
long long foo()
{
    long long x = 0 ; // long long, x may be incremented beyond the largest value that an int can hold 

	for ( int a = 0; a < 32768; a++) {
		for ( int b = 0; b < 32768; b++) {
			for ( int c = 0; c < 32768; c++) {
				++x ;
			}
		}
	}
	
	return x ;

    /* optimised away to the single line:
           return 35184372088832LL ;
    */    
}

https://gcc.godbolt.org/z/-hN0ZN
Last edited on
the language thing is tricky. I have the reverse... a simple md5 hash function .. java's is 3 times slower than what I wrote in c++. Java has no compiler flags etc when running it normally (not compiled to exe, but just running it) and the default setup is building optimized code. But you have nothing you can play with to try to make it faster beyond that, you are stuck with what it does or trying to out-guess it by manipulating the GC or something by doing screwy stuff in the code itself.

printing every loop is slow in any language. Its better to build up a string and dump it less frequently, or dump the program output to a file via command line, etc.

I ran your code on my machine with -O3 in g++ and it ran in a few seconds.
it runs instantly (subsecond) if you remove the prints, or redirect the output to file.

It does run to completion in a few min (10 ish?) if you turn optimization off. Don't recommend doing that here.
Last edited on
I tried it in CodeBlocks using different variants of C++ and in Visual Studio for C++

You didn't mention what version/edition of VS you are using; that could make a difference.

With VS2017 Community and VS2019 Community the maximum optimization available is -O2, in release mode. That can affect severely the speed optimization. As JLBorges and jonin pointed out, with -O3 enabled the optimization is much, much better.

The Community versions being free comes with a few drawbacks. Maybe the ability to do -O3 requires paying for the Professional and/or Enterprise editions.

same code in Java completes in a few seconds

Java isn't C++. The Java VM by default does a lot of optimizations that C++ compilers don't enable unless you specify them.
Last edited on
If you're using visual studio, there WONT be optimizations if you're running the code in debug mode. It's going to run the code as you typed it.

Right under the debug and team tabs up top, you'll see a drop down with "Debug" selected. Simply change it to "Release" and that program will run a lot faster.
Thanks for all the answers they gave me a lot to think about. I had never heard of optimizations so that gave me a lot to read about and play with. Salem was correct on Java aggressively removing the redundant loops, as soon as I placed an operation in the loop it slowed down comparably to the loops running in C++.
Unlike Java, C++ has the concept of undefined behaviour.
The original code snippet (on CodeBlocks/Visual Studio) that you posted engenders undefined behaviour (signed integer overflow).

"Because correct C++ programs are free of undefined behavior, compilers may produce unexpected results when a program that actually has UB is compiled with optimization enabled"
https://en.cppreference.com/w/cpp/language/ub#UB_and_optimization
Topic archived. No new replies allowed.