Home > OS >  How to enable optimization locally in Debug mode?
How to enable optimization locally in Debug mode?

Time:08-18

The following piece of code takes ~700 ms to run in Debug mode (Visual Studio 2017). I have read numerous questions on how to speed it up, but the majority of things I tried does not seem to have any effect.

By bisecting compiler flags, I found that the main slowdowns result from from /RTC1//RTCs (vs. /RTCu) and from /Od (vs. /O2). (I previously stated in the comments that they did not have a big effect, but I had been running the Debug/x86 configuration while modifying the Debug/x64 configuration...) _ITERATOR_DEBUG_LEVEL has a measurable, but negligible effect, and I don't worry too much about the remaining difference to Release mode.

My aim is to modify just a single piece of code (ideally, a function with just the std::equal call) that is not critical for routine debugging. I have been able to bring runtimes down "locally" (without changing global project options) by #pragma runtime_checks, basically countering /RTCs; but the same won't work for #pragma optimize, it seems.

// Debug (Default, /Od and /RTC1): 700 ms
// Debug (/Od /RTCs): 700 ms
// Debug (/Od /RTCu): 200 ms
// Debug (/Od /RTC1 with #pragma runtime_checks at main): 440 ms
// Debug (/Od /RTC1 with #pragma runtime_checks at top): 220 ms
// Debug (/Od): 200 ms
// Debug (/O2): 60 ms
// Debug (/O2 with _ITERATOR_DEBUG_LEVEL 0): 50 ms
// Release: 20 ms

#pragma runtime_checks( "s", off )
#pragma optimize( "gsy", on )
#define _ITERATOR_DEBUG_LEVEL 0

#include <algorithm>
#include <chrono>
#include <iostream>
#include <fstream>

using namespace std;
using clk = chrono::steady_clock;

// #pragma runtime_checks( "s", off )
int main()
{
  const ifstream is(R"(C:\Windows\explorer.exe)", ios::binary);

  auto begin = clk::now();
  equal(
    istreambuf_iterator<char>(is.rdbuf()),
    istreambuf_iterator<char>(),
    istreambuf_iterator<char>(is.rdbuf())
  );
  auto end = clk::now();

  cout << chrono::duration_cast<chrono::milliseconds>(end - begin).count();
  cout << " ms" << endl;
}

The documentation for #pragma runtime_checks says

You can't enable a run-time check that wasn't enabled by a compiler option.

I suspect something similar holds for #pragma optimize, in the sense that you cannot enable optimization that wasn't enabled by a compiler option. Could this be true? Is there anything else I can try to enforce optimization locally (apart from putting the function in its own file and configuring compiler options in the properties, which does work)?

CodePudding user response:

First of all, never put definitions of _HAS_ITERATOR_DEBUGGING or other standard library configuration macros in a source file. Put them in your project options. Otherwise you'll get into ODR errors (which MSVC is decently good at catching, but no point in tempting fate).

But to your main question, a lot of MSVC's standard library debug checks -- especially those related to iostreams -- are not controllable via macros, because they exist in pre-built libraries. It comes down to whether you're linking with the debug or release std library, rather than to what the header files see. The standard library LIBs/DLLs don't even know whether you had iterator debugging enabled, because they were compiled without the benefit of your #defines.

So if your slowdown is in the debug build of the standard library, there's nothing you can do about it except switch to the non-debug build of the standard library. (Which, BTW, will work even in debuggish configurations, with optimizations disabled and other debug-friendly compilation options set.)

CodePudding user response:

"/Od versus /O2".

That's not one change, that's a handful of changes. In particular, I find that inlining /Ob, which is included in /O2 makes a big difference. But it does not affect linking - where a function is inlined, there's simply no work left for the linker.

  • Related