float32x4_t acc = vdupq_n_f32(0.0f); // accumulator

for (int j = 0; j < 16; j += 4) {
    float32x4_t v_data = vld1q_f32(data + j);   // 加载4个float
    float32x4_t v_kern = vld1q_f32(kernel + j); // 加载4个float
    float32x4_t v_mul = vmulq_f32(v_data, v_kern); // 对应元素相乘
    acc = vaddq_f32(acc, v_mul); // 累加到acc里
}

// 最后合并acc寄存器中的4个元素
float result = vgetq_lane_f32(acc, 0)
             + vgetq_lane_f32(acc, 1)
             + vgetq_lane_f32(acc, 2)
             + vgetq_lane_f32(acc, 3);

以上是对卷积的优化。

因为卷积里的 weighted sum 本质就是:

sum += a[i] * b[i]

如果你一次只处理一个元素:

  • 需要 16 次 mul

  • 需要 16 次 add

  • 需要 16 次 load

  • CPU 负担重

NEON 版本一次处理 4 个元素:

  • 4 次 load → 1 次 vld1q

  • 4 次 mul → 1 次 vmulq

  • 4 次 add → 1 次 vaddq

🚀 单轮循环效能提升 4 倍(在理想情况下)

卷积的核心操作是:

sum = a0*w0 + a1*w1 + a2*w2 + ... + ak*wk

对于一个普通写法的代码:

float sum =
      src[i]   * w0
    + src[i+1] * w1
    + src[i+2] * w2;

对应的NEON版本的代码如下:

NEON 版本(一次处理4个样本)

卷积核:

float32x4_t vw0 = vdupq_n_f32(w0);
float32x4_t vw1 = vdupq_n_f32(w1);
float32x4_t vw2 = vdupq_n_f32(w2);

处理数据:

float32x4_t v0 = vld1q_f32(src + i);
float32x4_t v1 = vld1q_f32(src + i + 1);
float32x4_t v2 = vld1q_f32(src + i + 2);

加权求和:

float32x4_t vsum = vmulq_f32(v0, vw0);
vsum = vmlaq_f32(vsum, v1, vw1);
vsum = vmlaq_f32(vsum, v2, vw2);

写回:

vst1q_f32(dst + i, vsum);

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐