而(n> 1)比while(n)快25%?

orl*_*rlp -2 c performance gcc micro-optimization

我有两个逻辑上等效的函数:

long ipow1(int base, int exp) {
    // HISTORICAL NOTE:
    // This wasn't here in the original question, I edited it in,
    if (exp == 0) return 1;

    long result = 1;

    while (exp > 1) {
        if (exp & 1) result *= base;
        exp >>= 1;
        base *= base;
    }

    return result * base;
}

long ipow2(int base, int exp) { 
    long result = 1;

    while (exp) {
        if (exp & 1) result *= base;
        exp >>= 1;
        base *= base;
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)

注意:

这些循环是等价的,因为在前一种情况下我们正在返回result * base(处理exp已经或已经减少的情况1)但在第二种情况下我们正在返回result.


奇怪的是,两者都有,-O3并-O0 ipow1因此表现优于ipow2约25%.这怎么可能?

我在Windows 7,x64,gcc 4.5.2和编译gcc ipow.c -O0 -std=c99.

这是我的分析代码:

int main(int argc, char *argv[]) {
    LARGE_INTEGER ticksPerSecond;
    LARGE_INTEGER tick;
    LARGE_INTEGER start_ticks, end_ticks, cputime;

    double totaltime = 0;
    int repetitions = 10000;
    int rep = 0;
    int nopti = 0;

    for (rep = 0; rep < repetitions; rep++) {
        if (!QueryPerformanceFrequency(&ticksPerSecond)) printf("\tno go QueryPerformance not present");
        if (!QueryPerformanceCounter(&tick)) printf("no go counter not installed");  
        QueryPerformanceCounter(&start_ticks); 

        /* start real code */

        for (int i = 0; i < 55; i++) {
            for (int j = 0; j < 11; j++) {
                nopti = ipow1(i, j); // or ipow2
            }
        }

        /* end code */

        QueryPerformanceCounter(&end_ticks); 
        cputime.QuadPart = end_ticks.QuadPart - start_ticks.QuadPart;
        totaltime += (double)cputime.QuadPart / (double)ticksPerSecond.QuadPart;
    }   

    printf("\tTotal elapsed CPU time:   %.9f  sec  with %d repetitions - %ld:\n", totaltime, repetitions, nopti);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*igt 10

不,真的,这两个并不等同. ipow2如果ipow1没有,则返回正确的结果.

http://ideone.com/MqyqU

PS我不在乎你留下多少评论"解释"为什么它们是相同的,只需要一个反例就可以反驳你的说法.

关于你已经试图向你指出这一点的每个人的令人难以忍受的傲慢的问题的PPS -1.

  • 你是对的,`pow1`在`exp = 0`时失败了. (3认同)
  • @Ben Voigt:哦,该死的,我错误地解释了他的回答,我以为他在谈论'while`声明.现在我重读了它,我明白了.我曾为他如此咄咄逼人而道歉. (2认同)