如何优化分割常数?

时间:2017-07-01 16:03:54

标签: c algorithm optimization

除以常量的优化由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

但是,我不确定如何在没有大量开销的情况下使其更准确。

1 个答案:

答案 0 :(得分:1)

如果您可以触发“除以”的非常好的优化,那么您可以使用RCPPS指令(使用SSE / AVX)计算x/33659的倒数,从中受益。