除以常量的优化由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;
}
EDIT1:
#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,可以进行矢量化!)
EDIT2: 谢谢@ user2722968!应用RCPPS将使程序更快。
以下是我使用RCPPS进行快速恒定除数除法的实验实现:
https://github.com/ThinerDAS/didactic-spoon/blob/master/div.c
但是,我不确定如何在没有大量开销的情况下使其更准确。
答案 0 :(得分:1)
如果您可以触发“除以”的非常好的优化,那么您可以使用RCPPS指令(使用SSE / AVX)计算x/33659
的倒数,从中受益。