【发布时间】:2017-12-05 09:13:08
【问题描述】:
众所周知,gcc 对 除以 常数的优化得到了很好的优化 :)
现在我想知道如何优化除法常量。 gcc 没有帮助我,clang 也是。
也许我不擅长搜索这些信息,但我找不到关于除法常数优化的资料。 (相比之下,除以常数被很好地介绍了。)
#include <stdio.h>
int f(int x)
{
// can I optimize off the idiv opcode here?
return 33659/x;
}
int main()
{
int x;
scanf("%d", &x);
printf("%d", f(x));
return 0;
}
编辑1:
#include <stdio.h>
#define DIVIDEND 33
void f ( unsigned int* arr, int n )
{
for ( int i = 0; i < n ; i++ )
{
arr[i] = DIVIDEND / arr[i];
}
}
int main()
{
const int n = 1024;
unsigned int buf[n];
for ( int i = 0; i < n; i++ )
{
scanf ( "%u", buf + i );
}
f ( buf, n );
for ( int i = 0; i < n; i++ )
{
printf ( "%d", buf[i] );
}
return 0;
}
使用clang -O3 -march=native div.c -o div 进行优化仅展开循环,同时:
#include <stdio.h>
#define DIVIDEND 33
#define DIVISOR DIVIDEND
void f ( unsigned int* arr, int n )
{
for ( int i = 0; i < n ; i++ )
{
//arr[i] = DIVIDEND / arr[i];
arr[i] = arr[i] / DIVISOR;
}
}
int main()
{
const int n = 1024;
unsigned int buf[n];
for ( int i = 0; i < n; i++ )
{
scanf ( "%u", buf + i );
}
f ( buf, n );
for ( int i = 0; i < n; i++ )
{
printf ( "%d", buf[i] );
}
return 0;
}
使用相同的命令行会产生一堆可怕的 AVX2 代码。 (记住,被常数除法改写为shift+mul+add,可以向量化!)
编辑2: 感谢@user2722968!应用 RCPPS 将使程序更快。
这是我使用 RCPPS 进行快速恒分除法的实验实现:
https://github.com/ThinerDAS/didactic-spoon/blob/master/div.c
但是,我不确定如何在没有大量开销的情况下使其更准确。
【问题讨论】:
-
无论是 gcc 还是 clang 都没有显示任何优化,这并不是一个很好的暗示,这实际上不能很好地优化(或根本没有)。
-
了解 OP 认为在这种情况下可能进行哪些优化会很有趣。
-
我认为-no-优化是可能的。
-
如果红利为 0,则正在优化它:P。我认为这是唯一可以优化的情况。
-
@PSkocik 1/x 也可能值得优化。但无论如何,如果
x受到足够的限制,我可以想象可能的优化,比如仅 [1, ... 10] 等等。
标签: c algorithm optimization