【问题标题】:How to speed up this piece of STL code in Debug mode?如何在 Debug 模式下加速这段 STL 代码?
【发布时间】:2022-08-18 15:18:24
【问题描述】:

以下代码在调试模式下运行大约需要 700 毫秒 (Visual Studio 2017)。我已经阅读了很多关于如何加快速度的问题,但我尝试的大多数事情似乎都没有任何效果。

通过将编译器标志一分为二,我发现主要的减速来自/RTC1//RTCs(与/RTCu)和/Od(与/O2)。 (我之前在cmets中说过他们没有太大的影响,但是我一直在运行Debug/x86配置,同时修改Debug/x64配置...)_ITERATOR_DEBUG_LEVEL有一个可衡量的,但可以忽略不计的影响,我不要太担心释放模式的剩余差异。

我的目标是只修改一段代码(理想情况下,一个只有 std::equal 调用的函数),这对于常规调试并不重要。我已经能够通过#pragma runtime_checks 降低运行时“本地”(不更改全局项目选项),基本上是在对抗/RTCs;但似乎对#pragma optimize 也不起作用。

#pragma runtime_checks 的文档说

您不能启用编译器选项未启用的运行时检查。

// 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;
}

我怀疑#pragma optimize 存在类似的情况,因为您无法启用编译器选项未启用的优化。这可能是真的吗?还有什么我可以尝试在本地强制优化的吗?

  • 没有什么可以尝试的。就是这样。
  • 调试模式不是为了速度,而是为了调试。为什么要快速调试构建?
  • 以下代码需要 700 毫秒才能运行-- 除非你是超级英雄“闪电侠”,否则 700 毫秒对人类来说不算什么。
  • 您可以将需要调试的代码放在它自己的文件中,并将该文件设置为不优化,同时优化其余文件:stackoverflow.com/q/16515165/4342498
  • 另一种选择是围绕要调试的代码构建minimal reproducible example,这样您就可以使用要测试的代码。

标签: c++ performance debugging visual-c++ stl


【解决方案1】:

首先,永远不要将_HAS_ITERATOR_DEBUGGING 或其他标准库配置宏的定义放在源文件中。将它们放在您的项目选项中。否则,您将陷入 ODR 错误(MSVC 非常擅长捕捉,但没有任何意义)。

但是对于你的主要问题,很多 MSVC 的标准库调试检查——尤其与 iostreams 相关的那些 - 不能通过宏控制,因为它们存在于预构建的库中。它归结为您是链接到调试标准库还是发布标准库,而不是头文件看到的内容。标准库 LIB/DLL 甚至不知道您是否启用了迭代器调试,因为它们是在没有使用 #defines 的情况下编译的。

因此,如果您的减速是在标准库的调试版本中,那么除了切换到标准库的非调试版本之外,您无能为力。 (顺便说一句,即使在调试配置中也可以工作,禁用优化并设置其他调试友好的编译选项。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 2020-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多