Visual Studio 2019 版本16.3和16.4 包括对C++的改进 内联线 . 其中包括在优化后内联一些例程的能力,称为 “拉链。” 根据应用程序的不同,您可能会看到一些较小的代码质量改进和/或主要的构建时间(编译器吞吐量)改进。
Terry Mahaffey概述了 Visual Studio的内联决策 . 这详细说明了 内联线 制约因素和需要改进的领域,其中一些在这里特别相关:
- 这个 内联线 是递归的,可能经常重新做已经做过的工作。内联决策是上下文敏感的,对于同一个函数,重放其决策并不总是有利的。
- 这个 内联线 是非常 预算意识 . 它很难平衡可执行文件的大小和运行时的性能。
- 这个 内联线 世界观总是“预优化” d、 ““ 例如,它对复制传播和死控制路径的了解非常有限。
不幸的是,对于繁重的泛型编程来说,许多常见的编码模式和习惯用法都会遇到这些约束。考虑以下程序 特征库 :
Eigen::Matrix<float,-1,1,0,-1,1>::outerStride(void)
调用innerSize:
template<typename Derived> class DenseBase ... Index innerSize() const { return IsVectorAtCompileTime ? this->size() : int(IsRowMajor) ? this->cols() : this->rows(); }
这个例子 外三极 只返回其中一个成员。因此,它是完全内联扩展的最佳候选。为了实现这一点,编译器必须进行充分的计算和扩展 外三极 的 共18个 被叫人 ,每 胼胝体 属于 外三极 在模块中。这会消耗优化器吞吐量和 内联线 代码大小预算。值得一提的是,对“rows”和“cols”的调用 内联展开 同样,即使它们处于静态死路上。
那就好多了 如果优化器 内联 二线会员报税表 :
?outerStride@?$Matrix@N$0?0$0?0$0A@$0?0$0?0@Eigen@@QEBA_JXZ PROC ; Eigen::Matrix<double,-1,-1,0,-1,-1>::outerStride, COMDAT mov rax, QWORD PTR [rcx+8] ret 0
对于 日常工作 内联线现在将展开 已优化 一个例程的IR,绕过 获取IR并重新展开 被叫者。 这有扩张的双重目的 调用站点 更快,同时让内联程序更准确地度量预算。
首先,t 他 优化器 将进行总结 那个 外三极 是这种快速扩张的候选者 原来 编译 (记住 c2.dll试图 在调用方之前编译例程) . 那么,t 他 内联线 可以 替换对那个的呼叫 外三极 实例化 现场访问。
T 这种更快的内联扩展的候选者是叶函数 没有当地人 ,最多引用两个不同的参数, 全球 我 s ,或常量。在实践中 这个目标 最简单的getter和setter。
有很多这样的例子 外三极 在Eigen库中,一个大的调用树只扩展成一个或两个指令。大量使用Eigen的模块可以看到显著的吞吐量改进;我们测量了优化器占用25-50%的时间,这样的复制。
新的拉链还将使内线更准确地衡量其预算。 Eigen开发人员早就意识到MSVC不符合他们的规范(参见Eigenu STRONGu inline)。Zipliner应该有助于缓解一些这种担忧,因为ziplined例程现在被认为是一个几乎“免费”的内联。
这在VisualStudio2019中默认启用 16.3 ,以及16.4中的一些改进。拜托 下载Visual Studio 2019 尝试一下新的改进。我们可以通过下面的评论或电子邮件联系我们(visualcpp@microsoft.com). 如果您在Visual Studio或MSVC中遇到问题,或有任何建议,请通过“帮助”>“发送反馈”>“报告问题/在产品中提供建议”或通过 开发者社区 . 你也可以在Twitter上找到我们( @ 视觉 ).