【问题标题】:Does it gets faster than this?它会比这更快吗?
【发布时间】:2013-08-23 05:44:53
【问题描述】:

我当前用于计算 Legendre 符号的代码是

inline int legendre(int pa, int pm){
    register unsigned int a = pa;
    register unsigned int m = pm;
    int t = 1;
    int tmp=0;
    while (a>1) {
        tmp=__builtin_ctz(a);//a=x*2^tmp, where x is odd
        a>>=tmp;
        if(tmp&1 &&((m&7)==3 || (m&7)==5))//if it is an odd power and m=3,5 mod 8
            t=-t;//invert result
        if((a&3)==3 && (m&3)==3)//if m=3 mod 4 and a=3 mod 4
            t=-t;//invert result
        m %= a;
        tmp=a;
        a=m;
        m=tmp;//exchange variables
    }
    if (m == 1) return t;
    return 0;
}

这里可以进行任何优化吗?

【问题讨论】:

  • 可能更适合 codereview.stackexchange ,也 - 你使用什么语言?您可能想提一下(ps inline 在 C 语言中毫无意义,register 也是 - 编译器足够聪明,可以自己解决)
  • 我觉得你在炫耀 :D 代码看起来非常优化。即使假设可以更快地切换变量的符号,您也不会从中获得太多性能。
  • @BenjaminGruenbaum 虽然 inline 的影响可以忽略不计或没有影响,但 register 有。 (从 3100 毫秒到 2350 毫秒计算 legendre(1...10000000,982451653))
  • 您想在 1950 年代的机器上运行它吗?如果不是,那么偏执优化的意义何在:)
  • 这个问题似乎是题外话,因为它是关于代码审查的。它属于 codereview.stackexchange.com

标签: c number-theory


【解决方案1】:

从您已经编写的内容来看,似乎只能进行微不足道的优化。

// Get rid of the inline, it's pointless for functions this large.
// Some compilers might remove the inline for big functions.
int legendre(int pa, int pm){

// Rather than creating variables here, you COULD make global
// variables and assign them here. That would get rid of some
// time taken creating these local variables.
register unsigned int a = pa;
register unsigned int m = pm;
int t = 1;
int tmp=0;
while (a>1) {
    tmp=__builtin_ctz(a);//a=x*2^tmp, where x is odd
    a>>=tmp;

    // This just throws both if-statements into one.
    if((tmp&1 &&((m&7)==3 || (m&7)==5))
       || ((a&3)==3 && (m&3)==3)) t = -t;
    m %= a;
    tmp=a;
    a=m;
    m=tmp;//exchange variables
}
if (m == 1) return t;
return 0; 
}

除此之外,这段代码看起来还不错。我认为您不必担心。

【讨论】:

  • register 关键字对于任何体面的编译器都是毫无意义的
【解决方案2】:

我能看到的唯一可以优化的就是标志翻转:

t = (t ^ -1) + 1

t = ~t + 1; // I don't prefer this one

有趣的是 - 在某些平台上,尤其是虚拟机,它可能会变慢,所以你必须手动检查。

编辑

好的,发现了一个我忽略的好东西,你创建一个临时变量来交换它们,你可以使用 XOR 来交换它们,因为它们都是整数:

m = m^a;
a = a^m;
m = m^a;

这样 var 将交换它们的值而不需要 temp var

【讨论】:

  • 您是否检查过您的优化确实改善了情况?我希望它编译成相同的机器代码,因为我希望编译器相当聪明,但我的期望可能是错误的。
  • 嗯,我做到了......但我是一名 ActionScript 程序员,我们的编译器非常愚蠢,所以即使缩短变量名也会有所帮助。老实说 - 我不知道 C 或其他编译器是否这样做。此外,问题是关于一般代码优化,而不是编译器如何优化它,所以让我放松一下,让我炫耀一下:D
  • 没有性能差异。否定运算符在 x86 上生成 NEG 指令,因为 CPU 可以本机进行否定。没有比这更快的了。此外,XOR 交换方法速度较慢,而且是个坏主意。见en.wikipedia.org/wiki/XOR_swap_algorithm
  • 我只是喜欢在我出错的时候被淘汰 :) 谢谢你的文章,读起来很有趣;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
相关资源
最近更新 更多