【问题标题】:Is C++CLI optimized?C++CLI 优化了吗?
【发布时间】:2019-08-06 02:11:34
【问题描述】:

如果我用 C++CLI/托管 C++ 编写程序,编译器会执行任何优化吗?

我知道对于 C#,有一些优化是在编译时完成的,大部分优化是由 JIT 完成的。 C++CLI 也一样吗?

一个类似的问题:我可以为 C++CLI 做相当于 -O2 标志的操作吗?我已经知道“-c Release”标志,但我不清楚它做了什么样的优化。

谢谢!

【问题讨论】:

  • 您是使用 C++/CLI 编译器生成纯 MSIL,还是混合托管/原生?
  • 顺便说一句,Microsoft Visual C++ 编译器没有 -c Release 选项。我认为您指的是项目构建系统,它反过来调用真正的编译器。真正的编译器有传统的优化标志:/O options
  • 我使用 c++/cli 编译器来生成纯 MSIL,我相信,没有涉及原生。

标签: optimization c++-cli clr jit


【解决方案1】:

在生成本机代码时,C++/CLI 编译器支持与 Microsoft 的本机 C++ 编译器相同的优化。

在生成 MSIL 时,C++/CLI 编译器支持的优化数量较少(但仍比 C# 多),然后在 JIT 期间进行另一次优化(与适用于 C# 的 JIT 和 JIT 时间优化相同)。

例如,在生成 MSIL 时可以展开循环,但不能自动矢量化,因为 MSIL 没有 SIMD 指令。矢量化理论上仍然可以由 JIT 完成,但实际上 JIT 的资源限制意味着优化效果较差。

此外,由于语言设计,C++ 有一些优化,但 C# 没有。例如,C++ 模板(包括在 C++/CLI 中)针对模板参数的每个组合进行编译,而 .NET 泛型(包括在 C# 和 C++/CLI 中)仅基于泛型约束完全解析。

【讨论】:

  • 感谢您的精彩回答!您是否知道 C++/CLI 编译器在生成 MSIL 之前进行了哪些优化?
  • @Verdagon:我不认为微软发布了他们的 C++ 编译器执行的优化的完整列表,没关系哪些目标架构可用(将 MSIL 扔到编译器的指令集列表中)可以与 SSE、SSE2、AVX 一起启用/禁用可能并不完全准确,但这是一种有用的思考方式)。但是,您可以预期在输出 MSIL 之前会发生诸如常量传播和公共子表达式消除之类的事情。 MSIL 很容易阅读,您可以使用 /Od/O2 查看结果,看看优化了什么
【解决方案2】:

C++/CLI 代码总是在发布版本中进行优化,是的。谁是关键,你可以随意混合。太多本机 C++ 代码编译为 MSIL 时,这往往会出错。很难注意到,代码生成器可以处理任何兼容的 C++03 代码,并且很少会抱怨任何 C++1x 咒语。

一个很好的提醒,抖动与 C++ 编译器的后端没有太大区别。 MSIL 可以很好地与 LLVM 所需的 IR 进行比较。 MSVC++ 编译器用于本机代码的 IR 没有记录且不可见。

这使得将您包装在其自己的静态库或 DLL 中的本机 C++ 隔离是一种很好的做法。但是可以在功能级别进行混合,您可以使用#pragma un/managed 来回切换。

因此,正如您所猜测的那样,#pragma 非托管代码得到了优化器的全部喜爱,而#pragma managed 代码在运行时通过抖动得到了优化。您会发现在 this post 中记录的抖动优化。

【讨论】:

  • 在生成 MSIL 的过程中确实进行了很多优化,但它们受限于 (a) MSIL 的表现力——例如缺乏 SIMD,以及 (b) 需要保留通过反射可见的调用堆栈和代码结构(CAS 使用反射)
  • 当然,“总是”这个词太强了,无法描述发布配置中的优化——项目级设置会影响 MSIL 生成,附加调试器的存在通常会影响 JIT优化级别。
猜你喜欢
  • 2015-05-09
  • 1970-01-01
  • 2017-12-12
  • 2021-06-14
  • 1970-01-01
  • 2012-03-01
  • 1970-01-01
  • 2020-01-06
  • 2014-08-29
相关资源
最近更新 更多