By design, all compiler optimizations are disabled with -G. That enables the debugger to keep track of all the program variables that are otherwise strewn about in registers, or correspondence of source code lines to machine instructions, for example. If you have Heisenbugs that disappear when the code is compiled in debug mode, the first thing you would want to check for is race conditions. cuda-memcheck can help with that.
My favorite debugging technique is to instrument code with strategically placed printf() calls, logging the output to files. Before you dismiss this technique as quaint and old-fashioned, I will point out that I have successfully debugged codes, including CUDA programs, where others had failed. I got accustomed to printf-debugging when working on embedded systems where no modern debugger was available. Use of printf() is somewhat intrusive, you can also use a ring buffer to log binary data, which is less intrusive.