You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何C语言函数fib2的执行速度远快于fib与fib3?

为什么fib2函数的执行速度远快于fib和fib3?

编译环境

  • 编译命令:gcc -O3 main.c -o main
  • GCC版本:
gcc (GCC) 10.2.1 20200825 (Alibaba 10.2.1-3.6 2.32)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE

程序输出

102334155   fib Time spent: 0.185822 seconds
1059467309  fib2 Time spent: 0.036215 seconds  // 为什么更快?
102334155   fib3 Time spent: 0.181988 seconds

测试代码

#include <stdio.h>
#include <time.h>

long long fib2(int n)
{
    if (n <= 1)
    {
        return n;
    }
    else
    {
        long long first = fib2(n - 1);
        long long second = fib2(n - 2);
        return first * first + second * second;
    }
}

int fib(int n)
{
    if (n <= 1)
    {
        return n;
    }
    else
    {
        return fib(n - 1) + fib(n - 2);
    }
}

long long fib3(int n)
{
    if (n <= 1)
    {
        return n;
    }
    else
    {
        long long first = fib3(n - 1);
        long long second = fib3(n - 2);
        return first + second;
    }
}

void main()
{
    clock_t start1 = clock();
    printf("%d", fib(40));
    clock_t end1 = clock();
    double time_spent1 = (double)(end1 - start1) / CLOCKS_PER_SEC;
    printf("fib Time spent: %f seconds\n", time_spent1);
    printf("%d", fib2(40));
    clock_t end2 = clock();
    double time_spent2 = (double)(end2 - end1) / CLOCKS_PER_SEC;
    printf("fib2 Time spent: %f seconds\n", time_spent2);
    printf("%d", fib3(40));
    clock_t end3 = clock();
    double time_spent3 = (double)(end3 - end2) / CLOCKS_PER_SEC;
    printf("fib3 Time spent: %f seconds\n", time_spent3);
}

原因分析

这三个函数都是递归实现,但fib2的执行速度远超另外两个,关键在于GCC的-O3优化对fib2的递归结构做了更高效的处理,而fib和fib3的标准斐波那契递归逻辑没法享受到同样的优化,具体细节如下:

  • 递归逻辑的结构差异
    fib和fib3是标准的斐波那契递归:f(n) = f(n-1) + f(n-2)。这种结构里,计算f(n)必须分别算出f(n-1)和f(n-2),且两者之间没有直接推导关系,编译器没法用f(n-1)的结果推导f(n-2),导致递归调用次数是指数级的(约为O(φ^n),φ是黄金分割比),计算fib(40)时调用次数能达到上亿次。
    而fib2的逻辑是f(n) = f(n-1)^2 + f(n-2)^2,它计算的根本不是标准斐波那契数列(从输出结果也能看出fib2(40)的数值和另外两个不同)。重点是,编译器在-O3优化时,发现fib2(n-2)的调用结果可以通过fib2(n-1)的计算过程缓存下来,或者因为乘法操作的存在,编译器对这个递归结构做了深度内联和结果缓存,直接砍掉了大量重复的递归调用。

  • 优化空间的差异
    fib返回int类型,fib3返回long long,但两者递归逻辑完全一致,所以优化效果接近。而fib2的计算涉及乘法操作,编译器处理乘法时会把递归调用的结果存在寄存器中,避免了反复创建销毁栈帧,大幅降低了函数调用的开销。

  • 实际调用次数的差距
    标准斐波那契递归计算n=40需要上亿次调用,而fib2因为编译器的优化,实际调用次数可能接近线性级别,这直接导致了执行时间的巨大差距。


内容的提问来源于stack exchange,提问作者zmhuang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:24:51