C/C++ 是否对最短执行时间提供任何保证?
Does C/C++ offer any guarantee on minimal execution time?
为什么编译器似乎对什么都不做也不消除它们的循环很礼貌?
C 标准是否要求循环花费一些时间?
例子,代码如下:
void foo(void) {
while(1) {
for(int k = 0; k < 1000000000; ++k);
printf("Foo\n");
}
}
比这个慢:
void foo(void) {
while(1) {
for(int k = 0; k < 1000; ++k);
printf("Foo\n");
}
}
即使具有 -O3
优化级别。
我希望删除允许的空循环,从而在两个代码上获得相同的速度。
"time spent" 是应该由编译器保留的副作用吗?
否,花费的时间不算作受假设规则保护的可观察行为:
[C++14: 1.8/5]:
A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible executions of the corresponding instance of the abstract machine with the same program and the same input. However, if any such execution contains an undefined operation, this International Standard places no requirement on the implementation executing that program with that input (not even with regard to operations preceding the first undefined operation).
[C++14: 1.5/8]:
The least requirements on a conforming implementation are:
- Access to volatile objects are evaluated strictly according to the rules of the abstract machine.
- At program termination, all data written into files shall be identical to one of the possible results that execution of the program according to the abstract semantics would have produced.
- The input and output dynamics of interactive devices shall take place in such a fashion that prompting output is actually delivered before a program waits for input. What constitutes an interactive device is implementation-defined.
These collectively are referred to as the observable behavior of the program. [ Note: More stringent correspondences between abstract and actual semantics may be defined by each implementation. —end note ]
可以合法地优化这些循环,事实上,在某些情况下,标准会故意尝试使这样做变得更容易:
[C++14: 1.10/24]:
The implementation may assume that any thread will eventually do one of the following:
- terminate,
- make a call to a library I/O function,
- access or modify a volatile object, or
- perform a synchronization operation or an atomic operation.
[ Note: This is intended to allow compiler transformations such as removal of empty loops, even when termination cannot be proven. —end note ]
您的编译器实际上可能 "polite" 注意到 这些 程序中循环的意图似乎是减缓重复文本输出的发出. :)
您没有指定编译器,但我们假设它是 gcc
。
gcc 不会 删除空循环,至少不会根据 documentation。它包含以下文本:
Historically, GCC has not deleted “empty” loops under the assumption that the most likely reason you would put one in a program is to have a delay, so deleting them will not make real programs run any faster.
但是,如果优化器 "emptied" 空循环,它可以删除空循环,也就是说,如果循环包含优化器可以移出循环的代码,并且生成的循环是空的。
文档中不清楚这在最新版本中是否仍然适用。手册提到 "historically" 但没有说明原因。如果您使用有关您的确切平台和编译器的信息更新您的问题,也许可以给出更好的答案。
C 或 C++ 可执行文件没有最短执行时间,因为执行时间取决于许多平台特定问题,例如:
- 处理器时钟速率。
- 每条指令的时钟周期。
- 内部处理器执行优化。
- 中断。
- 处理器指令集/功能。
有些处理器支持乘法,有些则不支持。与具有乘法指令的进程相比,不支持乘法的处理器执行程序所需的时间更长。与浮点数相同。
处理器的内部运行速度各不相同。有一个通用的时间测量单位称为 "clock cycle"。大多数处理器供应商以时钟周期为单位指定指令的持续时间。由于缓存管理等内部支持,这种测量可能很困难。
一些处理器具有可以优化指令或指令模式执行的逻辑。一种优化是分支预测。
很多平台都有中断。例如,可能有一个 "system tick" 中断,它允许操作系统知道何时将执行切换到另一个程序。有些不是周期性的,例如 I/O 发生时。当程序被中断时,无法保证最短执行时间。
声明最短执行时间会对 C 和 C++ 语言的可移植性造成严重破坏。一些平台会希望比最短时间更快地执行代码。其他平台可能无法达到最短执行时间(但它们可以受益于像 C 这样的高级语言)。
还有,时间是怎么算的?
最短执行时间是否适用于延迟循环或轮询?
不,不能保证:(引自N1570, 5.1.2.3 Program execution)
1 The semantic descriptions in this International Standard describe
the behavior of an abstract machine in which issues of optimization
are irrelevant.
无论如何,C 标准只指定程序在抽象机器上执行时的行为,它可以有无限内存 and/or 个 CPU。
为什么编译器似乎对什么都不做也不消除它们的循环很礼貌?
C 标准是否要求循环花费一些时间?
例子,代码如下:
void foo(void) {
while(1) {
for(int k = 0; k < 1000000000; ++k);
printf("Foo\n");
}
}
比这个慢:
void foo(void) {
while(1) {
for(int k = 0; k < 1000; ++k);
printf("Foo\n");
}
}
即使具有 -O3
优化级别。
我希望删除允许的空循环,从而在两个代码上获得相同的速度。
"time spent" 是应该由编译器保留的副作用吗?
否,花费的时间不算作受假设规则保护的可观察行为:
[C++14: 1.8/5]:
A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible executions of the corresponding instance of the abstract machine with the same program and the same input. However, if any such execution contains an undefined operation, this International Standard places no requirement on the implementation executing that program with that input (not even with regard to operations preceding the first undefined operation).
[C++14: 1.5/8]:
The least requirements on a conforming implementation are:
- Access to volatile objects are evaluated strictly according to the rules of the abstract machine.
- At program termination, all data written into files shall be identical to one of the possible results that execution of the program according to the abstract semantics would have produced.
- The input and output dynamics of interactive devices shall take place in such a fashion that prompting output is actually delivered before a program waits for input. What constitutes an interactive device is implementation-defined.
These collectively are referred to as the observable behavior of the program. [ Note: More stringent correspondences between abstract and actual semantics may be defined by each implementation. —end note ]
可以合法地优化这些循环,事实上,在某些情况下,标准会故意尝试使这样做变得更容易:
[C++14: 1.10/24]:
The implementation may assume that any thread will eventually do one of the following:
- terminate,
- make a call to a library I/O function,
- access or modify a volatile object, or
- perform a synchronization operation or an atomic operation.
[ Note: This is intended to allow compiler transformations such as removal of empty loops, even when termination cannot be proven. —end note ]
您的编译器实际上可能 "polite" 注意到 这些 程序中循环的意图似乎是减缓重复文本输出的发出. :)
您没有指定编译器,但我们假设它是 gcc
。
gcc 不会 删除空循环,至少不会根据 documentation。它包含以下文本:
Historically, GCC has not deleted “empty” loops under the assumption that the most likely reason you would put one in a program is to have a delay, so deleting them will not make real programs run any faster.
但是,如果优化器 "emptied" 空循环,它可以删除空循环,也就是说,如果循环包含优化器可以移出循环的代码,并且生成的循环是空的。
文档中不清楚这在最新版本中是否仍然适用。手册提到 "historically" 但没有说明原因。如果您使用有关您的确切平台和编译器的信息更新您的问题,也许可以给出更好的答案。
C 或 C++ 可执行文件没有最短执行时间,因为执行时间取决于许多平台特定问题,例如:
- 处理器时钟速率。
- 每条指令的时钟周期。
- 内部处理器执行优化。
- 中断。
- 处理器指令集/功能。
有些处理器支持乘法,有些则不支持。与具有乘法指令的进程相比,不支持乘法的处理器执行程序所需的时间更长。与浮点数相同。
处理器的内部运行速度各不相同。有一个通用的时间测量单位称为 "clock cycle"。大多数处理器供应商以时钟周期为单位指定指令的持续时间。由于缓存管理等内部支持,这种测量可能很困难。
一些处理器具有可以优化指令或指令模式执行的逻辑。一种优化是分支预测。
很多平台都有中断。例如,可能有一个 "system tick" 中断,它允许操作系统知道何时将执行切换到另一个程序。有些不是周期性的,例如 I/O 发生时。当程序被中断时,无法保证最短执行时间。
声明最短执行时间会对 C 和 C++ 语言的可移植性造成严重破坏。一些平台会希望比最短时间更快地执行代码。其他平台可能无法达到最短执行时间(但它们可以受益于像 C 这样的高级语言)。
还有,时间是怎么算的?
最短执行时间是否适用于延迟循环或轮询?
不,不能保证:(引自N1570, 5.1.2.3 Program execution)
1 The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant.
无论如何,C 标准只指定程序在抽象机器上执行时的行为,它可以有无限内存 and/or 个 CPU。