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

避免频率缩放以稳定SIMD FMA性能的技术咨询

CPU FLOPS基准测试性能随迭代次数变化的原因与优化方案

测试程序与现象

该程序用于测试CPU核心的最大FLOPS,核心代码如下:

#include <immintrin.h>
#include <smmintrin.h>

#include <chrono>
#include <cstddef>
#include <iostream>

std::pair<float, float> fmadd_256(__m256 a[8], __m256 b[8], size_t sz) {
    __m256 c[8];
    float total_gflops{0};
    for (std::size_t i = 0; i < sz; i++) {
        c[0] = _mm256_fmadd_ps(a[0], b[0], c[0]);
        c[1] = _mm256_fmadd_ps(a[1], b[1], c[1]);
        c[2] = _mm256_fmadd_ps(a[2], b[2], c[2]);
        c[3] = _mm256_fmadd_ps(a[3], b[3], c[3]);
        c[4] = _mm256_fmadd_ps(a[4], b[4], c[4]);
        c[5] = _mm256_fmadd_ps(a[5], b[5], c[5]);
        c[6] = _mm256_fmadd_ps(a[6], b[6], c[6]);
        c[7] = _mm256_fmadd_ps(a[7], b[7], c[7]);

        total_gflops += 8 * 8 * 2;
    }
    float res = epilogue(c);
    return {res, total_gflops};
}

float epilogue(__m256 c[8]) {
    c[0] = _mm256_add_ps(c[0], c[1]);
    c[2] = _mm256_add_ps(c[2], c[3]);

    c[4] = _mm256_add_ps(c[4], c[5]);
    c[6] = _mm256_add_ps(c[6], c[7]);

    c[0] = _mm256_add_ps(c[0], c[3]);
    c[4] = _mm256_add_ps(c[4], c[6]);

    c[0] = _mm256_add_ps(c[0], c[4]);
    float res{0.0};
    for (size_t i = 0; i < 8; ++i) {
        res += c[0][i];
    }
    return res;
}

template <typename T>
void reporting(T duration, float flops, float res) {
    float gflops_sec = (flops * 1000.0 * 1000) / duration;
    std::cout << "THe inner product is: " << res << std::endl;
    std::cout << "GFLOPS/sec: " << gflops_sec << std::endl;
    std::cout << "total gflops: " << flops << std::endl;
    std::cout << "Duration: " << duration << std::endl;
}


int main(int argc, char** argv) {
    __m256 a[8];
    __m256 b[8];
    double total_res{0};
    constexpr size_t iters{5 * 10000000 / 1};
    constexpr size_t RUNS{100};
    fmadd_256(a, b, iters);  // test call
    double total_gflops{0};

    auto begin = std::chrono::high_resolution_clock::now();
    for (size_t i = 0; i < RUNS; ++i) {
        auto [res, gflops] = fmadd_256(a, b, iters);
        total_gflops += gflops;
        total_res += res;
        std::swap(a, b);
    }
    total_gflops *= 1e-9;
    auto end = std::chrono::high_resolution_clock::now();
    double duration =
        std::chrono::duration_cast<std::chrono::microseconds>(end - begin)
            .count();

    reporting(duration, total_gflops, total_res);
}

测试时发现,程序性能随迭代次数变化明显:小迭代次数时GFLOPS不稳定,随后进入120-130的平台期,迭代次数超过阈值后性能持续下降但保持稳定,具体数据如下:

迭代次数GFLOPS/sec
1×10⁶120
1×10⁷120
2×10⁷100
3×10⁷66
5×10⁷40

具体疑问

  1. 为何迭代次数足够大后,程序性能仍出现显著下降?
  2. 能否通过高频率采样验证时钟频率,确认是否是频率缩放导致的问题?
  3. 有没有方法消除性能波动(即便无法达到峰值性能)?

已尝试的操作:

  • 用taskset将程序绑定到特定CPU,以0.1秒间隔查看/proc/cpuinfo,仅发现频率小幅波动
  • 执行cpupower frequency-set --governor performance禁用频率缩放,命令执行成功,但/proc/cpuinfo仍显示频率变化,性能也未稳定
  • 测试环境为Alderlake架构笔记本

问题解答

1. 大迭代次数下性能下降的原因

核心原因是CPU热节流(Thermal Throttling):

  • 迭代次数较小时,CPU短时间高负载产生的热量不足以触发散热保护,能维持睿频或峰值频率运行,因此GFLOPS稳定在120-130区间
  • 迭代次数增大后,持续高负载让CPU温度快速上升,达到散热阈值后,CPU会主动降频控温,计算效率随之下降,GFLOPS数值降低
  • Alderlake笔记本的散热能力有限,长时间高负载下无法维持峰值频率,这是笔记本平台的普遍限制

另外,代码中c数组未初始化,可能引发不可预测的编译器优化或计算异常,虽不直接导致性能下降,但会影响测试结果的可靠性。

2. 高频率采样验证时钟频率

可以通过两种方式实现高频率采样,精准确认频率变化:

  • 使用perf工具实时采样:执行perf stat -e cpu-clock -I 100 ./your_program,其中-I 100表示每100毫秒采样一次,能直接记录程序运行期间的CPU频率波动
  • 脚本读取内核文件实现毫秒级采样:
#!/bin/bash
CPU=0  # 替换为绑定的核心编号
while true; do
    echo "$(date +%s.%N) $(cat /sys/devices/system/cpu/cpu$CPU/cpufreq/scaling_cur_freq)" >> freq_log.txt
    sleep 0.01
done

运行脚本的同时启动测试程序,事后分析freq_log.txt即可看到频率随时间的变化,判断是否因热节流导致降频。

3. 消除性能波动的方法

要获得稳定的测试结果,可从以下方面入手:

  • 控制测试时长:将单次测试总运行时间控制在1-2秒内,避免CPU因长时间负载触发热节流。调整iters和RUNS的组合,让总FLOPS对应的运行时间落在这个区间,既能避开短时间的不稳定,又不会触发降温
  • 彻底锁定CPU频率:
    部分Alderlake笔记本仅靠cpupower无法完全禁用硬件层面的频率调节,需进入BIOS关闭「Intel Speed Shift」或「Dynamic Frequency Scaling」选项,才能彻底锁定频率
  • 标准化测试环境:
    • 测试时关闭所有后台程序,避免资源抢占
    • 确保笔记本处于插电状态,电池模式下多数机型会限制CPU性能
    • 用taskset绑定到Alderlake的性能核(P核,通常是编号靠前的核心如cpu0、cpu1),避免调度到能效核(E核)导致性能波动
  • 修正代码问题:在fmadd_256函数开头添加memset(c, 0, sizeof(c));初始化累加器,避免未定义行为干扰测试结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 03:07:02