【问题标题】:How to optimize for dividing constant?如何优化除法常数?
【发布时间】: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+m​​ul+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


【解决方案1】:

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

【讨论】:

  • RCPPS 是一个很好的提示!该指令是一个非常粗略的近似值,并不可靠,但是它非常快。很难触发指令:(我会试试看。
猜你喜欢
  • 1970-01-01
  • 2019-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
相关资源
最近更新 更多