当前位置: 首页 > 知识库问答 >
问题:

我不明白DoNotOptimizeAway的定义

佘缪文
2023-03-14

我正在Celero git存储库中检查DoNotOptimizeAway的含义。但我还是不明白。请你用外行的话帮我理解一下好吗。尽你所能。

共有1个答案

邵弘致
2023-03-14

你没有包括定义,只是留档。我想你是在寻求帮助来理解它为什么存在,而不是定义。

它阻止编译器从重复循环中执行和提升工作,因此您可以重复相同的工作足够多的时间以进行测量。e、 g.在一个运行10亿次的循环中放置一些短的东西,然后你可以很容易地测量整个循环的时间(一秒钟左右)。看看x86的MOV真的能“免费”吗?为什么我根本不能复制这个?例如,在asm中手动执行此操作。如果您希望编译器生成这样的代码,则需要一个函数/宏,如DoNotOptimizeAway。

在禁用优化的情况下编译整个程序将是无用的:在C语句之间存储/重新加载所有内容会产生非常不同的瓶颈(通常是存储转发延迟)。请参阅添加冗余赋值会在没有优化的情况下编译代码时加快速度

参见惯用的绩效评估方法?对于一般的微基准陷阱

也许看看实际的定义也能有所帮助。

这个Q

escape宏来自Chandler Carruth的CppCon2015演讲,“调优C:基准测试、CPU和编译器!天哪!”。这篇演讲还详细介绍了为什么在编写微基准时需要它:在启用优化的情况下编译时,阻止整个循环优化。

(如果有问题,让编译器从循环中提升东西而不是重复计算它们会更难正确。如果函数足够大,不需要内联,那么制作一个函数__attribute__((noinline))会有所帮助。检查编译器的ami输出以查看它提升了多少设置。)

顺便说一句,GNU C/C的一个好的定义通常具有零额外成本:
asm易失性(":: "r"(my_var));编译为零asm指令,但要求编译器在其选择的寄存器中具有my_var的值。(并且由于asm易失性,必须在C抽象机器中“运行”多次)。

只有当编译器能够将它所参与的计算转换为其他计算时,这才会影响优化。(例如,在循环计数器上使用此选项将阻止编译器仅使用指针增量,并与结束指针进行比较,以对(i=0;i)进行正确的<代码>迭代次数。)

使用读-修改-写操作数,如asm volatile(“:”r“(my_var)) 将迫使编译器忘记它知道的关于值的所有范围限制或常数传播信息,并将其视为传入函数arg。e、 g.它是42,或者它是非负的。这可能会对优化产生更大的影响。

当他们说“开销在比较中被抵消”时,他们希望不是在谈论从单个计时结果中明确减去任何东西,也不是在谈论基准测试本身。

那是行不通的。现代CPU的性能分析不能通过增加每条指令的成本来实现。无序流水线执行意味着,如果前端(总指令吞吐量)不是瓶颈,并且它所需要的执行单元也不是瓶颈,那么额外的asm指令可以轻松地实现零额外成本。

如果它们的可移植定义类似于挥发性T接收器=输入

所以关于取消的说法听起来有点乐观。正如我上面解释的,加上上面的上下文/优化相关因素。有可能DoNotOptimizeAway

相关Q

  • 在基准测试时防止编译器优化
  • 避免使用内联ami优化off变量
  • "Escape"和"Cobber"在MSVC中的等效项
 类似资料:
  • 我需要改变复选框检查状态,但useCallback重新呈现组件很多次。我不明白它是如何工作的。我读过很多关于它的材料。 重新渲染的数量:

  • 我对遗传的理解是相当基础的。

  • 在我的Visual Studio项目中,我有以下几点,而且效果很好: 我只是想明白,编译器是否坚持我用“typename”作为d::result_of的前缀,因为它可能是模糊的,在d::result_of可以返回一个类,然后::类型可以是一个那个班的成员?这就是为什么它坚持要添加typename吗?如果是这样,那么为什么Visual Studio允许它?不合规吗? 另外,因为我已经读到了C 14或

  • 还不起作用。所以我放弃链接,我只是编码:

  • 问题内容: 我已经花了最后两天的时间来理解系统调用,但是我仍然在这里。让我直接谈谈这个问题。 在execlp的声明系统调用为与描述: 该为const char ARG和随后的椭圆在execl的(),execlp()和execle()函数可以作为为arg0,ARG1,…,ARGN被认为。 但是,我在课本中看到这样的系统调用:(“ …”是我们作为学生来识别的)。但是,此系统调用甚至与系统调用上的声明都

  • 问题内容: 为什么投给打破,当是? 问题答案: 不幸的是,没有办法对中的数组进行这样的转换。您将必须迭代数组并分别转换每个对象。 原因是安全类型,根本无法确保无需迭代遍历数组的内容就可以将其转换为Uri,这就是为什么必须对其进行迭代并分别进行转换的原因。 基本上因为可以被其他对象继承,所以不能保证数组仅包含对象。但是强制转换为超类型将是可行的,因为那样的话,类型安全就可以了。