【发布时间】:2017-10-06 23:06:04
【问题描述】:
我在 C 中有一个这样的函数(在伪代码中,删除了不重要的部分):
int func(int s, int x, int* a, int* r) {
int i;
// do some stuff
for (i=0;i<a_really_big_int;++i) {
if (s) r[i] = x ^ i;
else r[i] = x ^ a[i];
// and maybe a couple other ways of computing r
// that are equally fast individually
}
// do some other stuff
}
这段代码被如此频繁地调用,以至于这个循环实际上是代码中的一个速度瓶颈。我想知道几件事:
由于开关
s是函数中的常量,优秀的编译器会优化循环以使分支不会一直拖慢速度吗?如果没有,有什么好的方法可以优化这段代码?
====
这里有一个更完整示例的更新:
int func(int s,
int start,int stop,int stride,
double *x,double *b,
int *a,int *flips,int *signs,int i_max,
double *c)
{
int i,k,st;
for (k=start; k<stop; k += stride) {
b[k] = 0;
for (i=0;i<i_max;++i) {
/* this is the code in question */
if (s) st = k^flips[i];
else st = a[k]^flips[i];
/* done with code in question */
b[k] += x[st] * (__builtin_popcount(st & signs[i])%2 ? -c[i] : c[i]);
}
}
}
编辑 2:
如果有人好奇,我最终重构了代码并将整个内部 for 循环(使用 i_max)提升到外部,使 really_big_int 循环更简单,并且希望易于矢量化! (并且还避免了无数次做一堆额外的逻辑)
【问题讨论】:
-
如果可能,执行两个
if语句,每个语句都包含一个循环,而不是包含两个if语句的循环。然后你只检查一次条件,而不是a_really_big_int次。这取决于您当前循环中的其他内容是否以这种方式“可提取”。 -
@hnefatl 对——我想避免这种情况的原因是因为实际循环是几个嵌套循环,其中包含一些不完全不重要的逻辑,我不想重复码了很多次。但也许这是最好的解决方案
-
@Barmar 给出的示例变得可以简单地矢量化,因此
gcc绝对 将if()提升到循环之外。 -
@EOF 但也许他的实际代码与给出的示例并不完全相同。他说他遗漏了“不重要”的部分。它们可能对 GCC 优化器很重要。
-
@G.Meyer 你可以让所有变量都成为我关心的函数参数。唯一的一点是,我可以将它扔给我的编译器并获得其他人都可以验证的结果(不像 我 必须对你的代码进行钢锯来测试它)。
标签: c optimization compiler-optimization