C/C++是否能在最短的执行时间内提供任何保证?

Non*_*yme 41 c c++ compiler-optimization language-lawyer

为什么编译器似乎对没有做任何事情并且不消除它们的循环有礼貌?

C标准是否需要循环需要一些时间?

例如,以下代码:

void foo(void) {
    while(1) {
        for(int k = 0; k < 1000000000; ++k);
        printf("Foo\n");
    }
}
Run Code Online (Sandbox Code Playgroud)

运行速度比这个慢:

void foo(void) {
    while(1) {
        for(int k = 0; k < 1000; ++k);
        printf("Foo\n");
    }
}
Run Code Online (Sandbox Code Playgroud)

即使有-O3优化水平.我希望删除允许的空循环,从而在两个代码上获得相同的速度.

"花费的时间"是否应该由编译器保留的副作用?

Lig*_*ica 43

不,花费的时间不算作可观察行为受as-if规则保护:

[C++14: 1.8/5]: 执行格式良好的程序的一致实现应该产生与具有相同程序和相同输入的抽象机的相应实例的可能执行之一相同的可观察行为.但是,如果任何此类执行包含未定义的操作,则此国际标准不要求使用该输入执行该程序的实现(甚至不考虑第一个未定义操作之前的操作).

[C++14: 1.5/8]: 符合实施的最低要求是:

  • 严格根据抽象机器的规则来评估对volatile对象的访问.
  • 在程序终止时,写入文件的所有数据应与根据抽象语义产生的程序执行的可能结果之一相同.
  • 交互设备的输入和输出动态应以这样一种方式进行,即在程序等待输入之前提示输出实际被传送.构成交互设备的是实现定义的.

这些统称为程序的可观察行为. [注意:每个实现可以定义抽象和实际语义之间更严格的对应关系. - 尾注]

这些循环可以在法律上进行优化,实际上,在某些情况下,标准会故意尝试这样做更容易:

[C++14: 1.10/24]: 实现可以假定任何线程最终将执行以下操作之一:

  • 终止,
  • 调用库I/O函数,
  • 访问或修改易失性对象,或
  • 执行同步操作或原子操作.

[注意:这是为了允许编译器转换,例如删除空循环,即使无法证明终止也是如此. - 尾注]

事实上,你的编译器可能会"注意" 这些程序中循环的意图似乎在减慢重复文本输出的发射.:)

  • 令人讨厌的是,问题机构本身规定了"C标准". (4认同)

pip*_*ipe 28

你没有指定编译器,但我们假设它是gcc.

GCC并没有删除空循环,至少没有根据文档.它包含以下文本:

从历史上看,GCC没有删除"空"循环,假设你将一个程序放入程序的最可能的原因是延迟,所以删除它们不会使真正的程序运行得更快.

但是,如果优化器"清空"它,它可以删除空循环,也就是说,如果循环包含优化器可以移出循环的代码,并且结果循环为空.

从文档中不清楚在最新版本中是否仍然如此.手册提到"历史性"而没有说明原因.如果您使用有关您的确切平台和编译器的信息更新您的问题,可能会给出更好的答案.

  • 一个例子可能有帮助,比如`int main(void){int i,k; for(i = 0; i <1000000; ++ i)++ k; 放( "完成"); ``,`k`的值从未使用过,因此可以优化`k`.因为`k`的增量永远不会发生,所以循环甚至不需要增加`k`,因为这是它唯一的工作.因此,编译器可以优化循环.`i`的值现在也未被使用,因此它也可以被优化掉,留下`int main(void){puts("Done");}`作为结果优化程序.我在GCC 5.2.0中编译为64位Windows代码时会发生这种情况. (8认同)
  • @ChronoKitsune更进一步,让我们说你回来了`k`而不是忽略它.在这种特定情况下,编译器可以*仍然*删除循环,并简单地将程序优化为类似`int main(void){return 0xf4240;}` (2认同)

Tho*_*ews 7

C或C++可执行文件没有最短的执行时间,因为执行时间取决于许多特定于平台的问题,例如:

  1. 处理器时钟频率.
  2. 每条指令的时钟周期.
  3. 内部处理器执行优化.
  4. 中断.
  5. 处理器指令集/功能.

有些处理器支持乘法,有些则不支持.与具有乘法指令的进程相比,不支持乘法的处理器执行程序所需的时间更长.与浮点相同.

处理器的内部运行速度各不相同.有一个共同的时间测量单位称为"时钟周期".大多数处理器供应商在时钟周期中指定指令的持续时间.由于内部支持(例如缓存管理),此测量可能很困难.

某些处理器具有可以优化指令或指令模式执行的逻辑.一种优化是分支预测.

许多平台都有中断.例如,可能存在"系统节拍"中断,其允许操作系统知道何时将执行切换到另一个节目.有些不是那么周期性,例如I/O发生时.程序中断时无法保证最短执行时间.

说明最短执行时间会对C和C++语言的可移植性造成严重破坏.某些平台希望比最短时间更快地执行代码.其他平台可能无法实现最短的执行时间(但它们可以从像C这样的高级语言中受益).

另外,如何衡量时间?

最小执行时间是否适用于延迟循环或轮询?