是否允许C ++优化器在函数调用之间移动语句? [英] Is a C++ optimizer allowed to move statements across a function call?

查看:89
本文介绍了是否允许C ++优化器在函数调用之间移动语句?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:此处完全没有多线程.只是优化的单线程代码.

Note: No multithreading at all here. Just optimized single-threaded code.

函数调用引入了序列点. (显然.)

A function call introduces a sequence point. (Apparently.)

是否遵循不允许编译器(如果优化程序内联函数) 在函数指令之前/之后移动/混合任何指令? (只要它可以证明"没有明显的效果即可.)

Does it follow that a compiler (if the optimizer inlines the function) is not allowed to move/intermingle any instructions prior/after with the function's instructions? (As long as it can "proove" no observable effects obviously.)

说明背景:

现在,有一个不错的文章 wrt . C ++的基准测试类,作者说:

Now, there is a nice article wrt. a benchmarking class for C++, where the author stated:

我们时间的代码不会被优化器重新排列,并且始终会 介于对now()的开始/结束调用之间,因此我们可以保证 时间将是有效的.

The code we time won’t be rearranged by the optimizer and will always lie between those start / end calls to now(), so we can guarantee our timing will be valid.

我问他如何确定,尼克对此回答:

to which I asked how he can be sure, and nick replied:

您可以在此答案中查看评论 https://codereview.stackexchange.com/a/48884 .我引用:我会 谨慎地计时由于以下原因无法起作用的事物 允许编译器执行的优化.我不确定 排序要求和可观察到的行为理解 这样的程序.通过函数调用,不允许编译器执行 在调用点上移动语句(它们在之前或之后被排序 通话结束后).

You can check the comment in this answer https://codereview.stackexchange.com/a/48884. I quote : "I would be careful about timing things that are not functions because of optimizations that the compiler is allowed to do. I am not sure about the sequencing requirements and the observable behavior understanding of such a program. With a function call the compiler is not allowed to move statements across the call point (they are sequenced before or after the call)."

我们所做的基本上是抽象可调用对象(函数,lambda,块 代码被lambda包围)并进行信号处理 measure结构内部的callable(factor) 障碍(不是多线程的障碍,我相信我传达了 消息).

What we do is basically abstract the callable (function, lambda, block of code surrounded by lambda) and have a signle call callable(factor) inside the measure structure that acts as a barrier (not the barrier in multithreading, I believe I convey the message).

我对此不太确定,尤其是引号:

I am quite unsure about this, especially the quote:

通过函数调用,不允许编译器执行 在调用点上移动语句(它们在之前或之后被排序 通话结束后.)

With a function call the compiler is not allowed to move statements across the call point (they are sequenced before or after the call).

现在,我一直给人的印象是,当优化器内联某些功能时(在(简单的)基准测试场景中很可能是这种情况),只要不影响其效果,就可以随意重新排列可观察到的行为.

Now, I was always under the impression that when an optimizer inlines some function (which may very well be the case in a (simple) benchmark scenario), it is free to rearrange whatever it likes as long as it does not affect observable behavior.

也就是说,就语言/优化程序而言,这两个代码片段完全相同:

That is, as far as the language / the optimizer are concerned, these two snippets are exactly the same:

void f() {
  // do stuff / Multiple statements
}

auto start = ...;
f();
auto stop = ...;

vs.

auto start = ...;
  // do stuff / Multiple statements
auto stop = ...;

推荐答案

现在,我总是觉得,当优化程序内联时 一些功能(在(简单的)基准测试中很可能是这种情况 场景),只要它喜欢就可以随意重新排列 不会影响可观察到的行为.

Now, I was always under the impression that when an optimizer inlines some function (which may very well be the case in a (simple) benchmark scenario), it is free to rearrange whatever it likes as long as it does not affect observable behavior.

绝对是.从理论上讲,优化程序甚至不需要内联它.

It absolutely is. The optimizer doesn't even need to inline it for this to occur in theory.

但是,计时功能是可以观察到的,特别是在系统方面,它们是I/O.如果以与其他I/O调用不同的顺序执行,则优化器无法知道I/O会产生相同的结果(显然不会),这可能包括非显而易见的事情,例如甚至可以调用syscall的内存分配调用获得他们的记忆.

However, timing functions are observable behaviour- specifically, they are I/O on the part of the system. The optimizer cannot know that that I/O will produce the same outcome (it obviously won't) if performed in a different order to other I/O calls, which can include non-obvious things like even memory allocation calls that can invoke syscalls to get their memory.

这基本上意味着,对于大多数函数调用而言,优化器无法进行大量的重新安排,因为可能涉及大量的状态而无法推理.

What this basically means is that by and large, for most function calls, the optimizer can't do a great deal of re-arranging because there's potentially a vast quantity of state involved that it can't reason about.

此外,优化器无法真正知道重新安排函数调用实际上会使代码运行得更快,并使调试起来更加困难,因此,他们没有太多动机来解决问题符合程序的规定顺序.

Furthermore, the optimizer can't really know that re-arranging your function calls will actually make the code run faster, and it will make debugging it harder, so they don't have a great deal of incentive to go screwing around with the program's stated order.

从理论上讲,优化器可以做到这一点,但实际上并不是这样,因为这样做不会带来很多好处.

Basically, in theory the optimizer can do this, but in reality it won't because doing so would be a massive undertaking for not a lot of benefit.

如果您的基准测试相当琐碎,或者实际上完全由诸如整数加法之类的原始操作组成,那么您只会遇到这样的条件-在这种情况下,您还是要检查程序集.

You'll only encounter conditions like this if your benchmark is fairly trivial or consists virtually entirely of primitive operations like integer addition- in which case you'll want to check the assembly anyway.

这篇关于是否允许C ++优化器在函数调用之间移动语句?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆