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

SSE浮点数组求和的向量化调用结构:哪种实现方案更优?

大浮点数组SSE向量求和的实现方案与选型探讨

针对不熟悉SSE intrinsic的开发者,我们探讨大浮点数组求和场景下,加载、加法、存储操作的最优结构。需求是通过循环持续更新结果数组,最终得到各位置的累加求和值,以下是两种朴素实现方案:

方案一:调用者循环内累加

创建临时数组存储单次128位运算结果,再与结果数组累加,代码实现如下:

#include <stdio.h>
#include <xmmintrin.h>

void compute (const float *a, const float *b, float *c)
{
    __m128 va = _mm_loadu_ps(a);
    __m128 vb = _mm_loadu_ps(b);
    __m128 vc = _mm_add_ps(va, vb);
    _mm_storeu_ps(c, vc);
}

int main (void) {

  float a[] = { 1.1, 2.2, 3.3, 4.4, 1.1, 2.2, 3.3, 4.4 },
        b[] = { 1.1, 2.2, 3.3, 4.4, 1.1, 2.2, 3.3, 4.4 },
        c[4] = { 0 };

  for (int i = 0; i < 8; i += 4) {
    float tmp[4] = { 0 };
    compute (a + i, b + i, tmp);
    compute (c, tmp, c);
  }

  for (int i = 0; i < 4; i++) {
    printf ("c[%d]: %5.2f\n", i, c[i]);
  }
}

方案二:compute函数内直接更新结果

在compute函数中完成结果数组的加载、累加与存储,代码实现如下:

#include <stdio.h>
#include <xmmintrin.h>

void compute (const float *a, const float *b, float *c)
{
    __m128 va = _mm_loadu_ps(a);
    __m128 vb = _mm_loadu_ps(b);
    __m128 vt = _mm_add_ps(va, vb);
    
    __m128 vc = _mm_loadu_ps(c);
    __m128 vr = _mm_add_ps(vt, vc);
    
    _mm_storeu_ps(c, vr);
}

int main (void) {
  
  float a[] = { 1.1, 2.2, 3.3, 4.4, 1.1, 2.2, 3.3, 4.4 },
        b[] = { 1.1, 2.2, 3.3, 4.4, 1.1, 2.2, 3.3, 4.4 },
        c[4] = { 0 };

  for (int i = 0; i < 8; i += 4) {
    compute (a + i, b + i, c);
  }
  
  for (int i = 0; i < 4; i++) {
    printf ("c[%d]: %5.2f\n", i, c[i]);
  }
}

原本担忧方案一存在额外的compute函数调用开销,但实际编译后两者生成的汇编代码几乎一致,仅方案二的compute函数多一条vaddps指令。除了通过对比汇编代码判断性能差异外,是否存在通用原则可以指导这类SSE向量求和场景的方案选型?


内容的提问来源于stack exchange,提问作者David C. Rankin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 22:24:54