【发布时间】:2023-03-17 10:10:02
【问题描述】:
我正在分析 C 中的 pre vs post 递增运算符(出于好奇,不是出于微优化目的!),我得到了一些令人惊讶的结果。我预计后增量运算符会更慢,但我所有的测试都表明它(非平凡)更快。我什至查看了在 gcc 中使用 -S 标志生成的汇编代码,并且 post 有一条额外的指令(如预期的那样)。谁能解释一下?我在 Arch Linux 上使用 gcc 4.8.1。
这是我的代码。
编辑:我的代码中有一个整数溢出错误。它不会影响问题,但您应该注意实际的迭代次数与传入的参数不同。
Post.c:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if (argc < 2) {
printf("Missing required argument\n");
exit(1);
}
int iterations = atoi(argv[1]);
int x = 1;
int y;
int i;
for (i = 0; i < iterations; i++) {
y = x++;
}
printf("%d\n", y);
}
Pre.c:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if (argc < 2) {
printf("Missing required argument\n");
exit(1);
}
int iterations = atoi(argv[1]);
int x = 1;
int y;
int i;
for (i = 0; i < iterations; i++) {
y = ++x;
}
printf("%d\n", y);
}
结果如下:
$ gcc post.c -o post
$ gcc pre.c -o pre
$ I=100000000000; time ./post $I; time ./pre $I
1215752192
real 0m2.777s
user 0m2.777s
sys 0m0.000s
1215752193
real 0m3.140s
user 0m3.137s
sys 0m0.003s
不久前我还写了一个timing script。运行结果相同:
$ I=100000000000; comptime "./pre $I" "./post $I"
3193 3133 3157 3143 3133 3153 3147 3150 3143 3146 3143
2743 2767 2700 2727 2700 2697 2727 2710 2680 2783 2700
Mean 1: 3149.18
Mean 2: 2721.27
SD 1: 6.1800
SD 2: 21.2700
输出大多是自我解释的,但想法是它运行两个程序 10 次(默认情况下)并以毫秒为单位计算结果的平均值和标准差。
我已将 gcc 为 post.c 和 pre.c 生成的汇编代码包含在 pastebin 中,因为我不想在这篇文章中添加一些不必要的东西。
很抱歉再次引发这场争论,但这些数字对我来说似乎很奇怪。
【问题讨论】:
-
使
yvolatile 并再次运行它只是为了好玩。之后,完全抛弃x,从两个for循环中删除增量步骤,只使用y = ++i;(显然分别使用i++)。我知道它在我的装备上做什么,对你的很好奇。 similar test 只是为了兴趣,虽然它是 C++ 代码。 -
@WhozCraig。很酷。时间几乎相同。
-
@WhozCraig 移除 volatile 变化不大。
-
好吧,100000000000 不适合普通的
int。在atoi()后面加上printf("%d", iterations);,你就会明白我的意思了。 -
@Emmet,啊,这是一个愚蠢的错误。我应该从输出中意识到。不要认为它与问题有关,但无论如何我都会解决它。
标签: c performance profiling post-increment pre-increment