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

两个C语言tuple乘法函数的性能差异及原因咨询

问题

若需调用以下两个C语言tuple乘法函数数百万次,二者的性能差异是什么?我最初认为tuple_mul1无需额外栈分配,性能更优,但测试显示tuple_mul2更快:2亿次调用中,tuple_mul1耗时约1.55秒,tuple_mul2耗时约1秒(使用cc无优化选项编译)。请解释该现象原因。

相关代码

typedef struct s_tuple{
    double  x;
    double  y;
    double  z;
    double  w;
    double  m;
    double  n;
    double  o;
    double  p;
}   t_tuple;

// (1)
t_tuple tuple_mul1(const double q, t_tuple a)
{
    a.x *= q;
    a.y *= q;
    a.z *= q;
    a.w *= q;
    a.m *= q;
    a.n *= q;
    a.o *= q;
    a.p *= q;
    return a;
}

// (2)
t_tuple tuple_mul2(const double q, const t_tuple a)
{
    t_tuple b;

    b.x = a.x * q;
    b.y = a.y * q;
    b.z = a.z * q;
    b.w = a.w * q;
    b.m = a.m * q;
    b.n = a.n * q;
    b.o = a.o * q;
    b.p = a.p * q;
    return b;
}

测试代码

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

typedef struct s_tuple{
    double  x;
    double  y;
    double  z;
    double  w;
    double  m;
    double  n;
    double  o;
    double  p;
}   t_tuple;

// (1)
t_tuple tuple_mul1(const double q, t_tuple a)
{
    a.x *= q;
    a.y *= q;
    a.z *= q;
    a.w *= q;
    a.m *= q;
    a.n *= q;
    a.o *= q;
    a.p *= q;
    return a;
}

// (2)
t_tuple tuple_mul2(const double q, const t_tuple a)
{
    t_tuple b;

    b.x = a.x * q;
    b.y = a.y * q;
    b.z = a.z * q;
    b.w = a.w * q;
    b.m = a.m * q;
    b.n = a.n * q;
    b.o = a.o * q;
    b.p = a.p * q;
    return b;
}

int main(int ac, char **av)
{
    int         i;
    long int    n;
    double      q;
    t_tuple     a;
    clock_t     start, end;

    q = 0.7;
    a.x = 1.5;
    a.y = 2;
    a.z = 35897.78;
    a.w = 4.6698;
    a.m = 5.5;
    a.n = 1065;
    a.o = 11.6887;
    a.p = 109090808.789;
    if (ac > 1)
    {
        n = atol(av[1]);
        double execution_time;
        start = clock();
        for (i = 0; i < n; i++)
            tuple_mul1(q, a);
            // tuple_mul2(q, a);
        end = clock();
        execution_time = ((double)(end - start))/CLOCKS_PER_SEC;
        printf("exec_time = %f\nn = %.f * 1e6\n", execution_time, n / 1e6);
    }
}
原因解释

在无优化编译的场景下,两个函数的性能差异核心源于内存访问模式的不同,具体如下:

  1. 成员操作的内存周期差异

    • tuple_mul1中每个成员执行*=操作:先从栈上读取成员值,乘以q后写回原栈位置,属于读-修改-写三步操作。无优化时,编译器不会合并这些步骤,CPU需要等待写操作完成才能进行下一次读,产生额外内存延迟。
    • tuple_mul2中每个成员执行直接赋值:从栈上读取源结构体成员值,乘以q后写入新结构体位置,属于读-写两步操作。源结构体成员处于只读状态,更容易被CPU缓存命中,且无同一内存地址的重复读写冲突,流水线执行更顺畅。
  2. 栈分配的实际开销可忽略
    你之前认为tuple_mul1无需额外栈分配,但tuple_mul2中创建的t_tuple b只是栈指针的简单移动,几乎没有额外开销;而tuple_mul1的读-修改-写带来的内存周期开销,远大于栈分配的成本。

  3. 返回值拷贝的开销基本一致
    两个函数返回结构体时,都需要将结果拷贝到调用者指定位置,这部分开销在无优化下基本相同,不会造成明显性能差异。

综上,tuple_mul2更高效的内存访问模式,使其在无优化编译下比tuple_mul1更快。


内容的提问来源于Stack Exchange,提问作者BobDeTunis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:20:56