Files
Alicho/docs/api/simd.md
2025-10-28 10:27:49 +08:00

34 KiB
Raw Permalink Blame History

SIMD优化API参考

目录

概述

SIMD单指令多数据是一种并行处理技术可以在单个CPU指令周期内同时处理多个数据元素。对于音频处理这种数据密集型应用SIMD可以显著提高计算效率。音频后端系统提供了一套全面的SIMD优化API支持x86平台的SSE/AVX/AVX2/AVX-512以及ARM平台的NEON指令集。

核心特性:

  • 自动CPU特性检测运行时检测可用的SIMD指令集
  • 动态函数分发:根据可用的指令集选择最佳实现
  • 对齐内存管理:确保数据正确对齐以获得最佳性能
  • 丰富的优化函数提供常见音频处理操作的SIMD优化版本
  • 跨平台支持同时支持x86Intel/AMD和ARM架构
  • 统一API:提供简洁一致的接口,隐藏复杂实现细节

SIMD优化系统架构

┌─────────────────────────┐
│  应用代码                │
└───────────┬─────────────┘
            │
┌───────────▼─────────────┐
│  SIMD函数调用            │◄────┐
└───────────┬─────────────┘     │
            │                   │
┌───────────▼─────────────┐     │
│  函数分发器              │     │
└───────────┬─────────────┘     │
            │                   │
┌───────────▼─────────────┐     │
│  特性检测                │     │
└─────────────────────────┘     │
                                │
┌─────────────────────────┐     │
│  函数实现注册           │─────┘
│                         │
│  ┌───────────────────┐  │
│  │  标量实现         │  │
│  └───────────────────┘  │
│  ┌───────────────────┐  │
│  │  SSE实现          │  │
│  └───────────────────┘  │
│  ┌───────────────────┐  │
│  │  AVX实现          │  │
│  └───────────────────┘  │
│  ┌───────────────────┐  │
│  │  AVX2实现         │  │
│  └───────────────────┘  │
│  ┌───────────────────┐  │
│  │  AVX-512实现      │  │
│  └───────────────────┘  │
│  ┌───────────────────┐  │
│  │  NEON实现         │  │
│  └───────────────────┘  │
└─────────────────────────┘

CPU特性检测

支持的指令集

音频后端系统支持以下SIMD指令集

x86/x64平台

  • SSE/SSE2128位寄存器支持4个单精度浮点数或2个双精度浮点数
  • SSE3/SSSE3:增加了水平操作和复杂算术
  • SSE4.1/SSE4.2:增加了点积、混合和字符串处理指令
  • AVX256位寄存器支持8个单精度或4个双精度浮点数
  • AVX2:增加了整数指令和散布/收集操作
  • FMA:融合乘加指令,提高精度和性能
  • AVX-512512位寄存器支持16个单精度或8个双精度浮点数

ARM平台

  • NEON128位寄存器支持4个单精度浮点数
  • NEON FP16支持半精度16位浮点数

运行时检测

系统使用CPUFeatureDetector类在运行时检测CPU支持的指令集

namespace audio_backend::simd {

enum class CPUFeature : uint32_t {
    // x86/x64 SIMD特性
    SSE = 1 << 0,
    SSE2 = 1 << 1,
    SSE3 = 1 << 2,
    SSSE3 = 1 << 3,
    SSE41 = 1 << 4,
    SSE42 = 1 << 5,
    AVX = 1 << 6,
    AVX2 = 1 << 7,
    FMA = 1 << 8,
    AVX512F = 1 << 9,
    AVX512VL = 1 << 10,
    AVX512BW = 1 << 11,
    AVX512DQ = 1 << 12,
    
    // ARM NEON特性
    NEON = 1 << 20,
    NEON_FP16 = 1 << 21,
    
    // 其他特性
    POPCNT = 1 << 30,
    BMI1 = 1 << 31
};

enum class SIMDLevel {
    NONE,       // 无SIMD支持纯标量
    SSE,        // SSE/SSE2
    SSE3,       // SSE3/SSSE3
    SSE4,       // SSE4.1/SSE4.2
    AVX,        // AVX
    AVX2,       // AVX2 + FMA
    AVX512,     // AVX-512
    NEON,       // ARM NEON
    NEON_FP16   // ARM NEON with FP16
};

}

特性查询

应用程序可以通过以下全局函数查询CPU特性

// 获取CPU详细信息
const CPUInfo& get_cpu_info();

// 检查是否支持特定SIMD特性
bool cpu_supports(CPUFeature feature);

// 获取最高支持的SIMD级别
SIMDLevel get_max_simd_level();

// 获取推荐使用的SIMD级别考虑性能和兼容性
SIMDLevel get_recommended_simd_level();

使用示例:

void print_cpu_info() {
    const auto& info = audio_backend::simd::get_cpu_info();
    
    std::cout << "CPU信息" << std::endl;
    std::cout << "  厂商:" << info.vendor << std::endl;
    std::cout << "  品牌:" << info.brand << std::endl;
    std::cout << "  逻辑核心数:" << info.logical_cores << std::endl;
    std::cout << "  物理核心数:" << info.physical_cores << std::endl;
    
    std::cout << "SIMD支持" << std::endl;
    if (audio_backend::simd::cpu_supports(audio_backend::simd::CPUFeature::SSE))
        std::cout << "  SSE支持" << std::endl;
    if (audio_backend::simd::cpu_supports(audio_backend::simd::CPUFeature::AVX))
        std::cout << "  AVX支持" << std::endl;
    if (audio_backend::simd::cpu_supports(audio_backend::simd::CPUFeature::AVX2))
        std::cout << "  AVX2支持" << std::endl;
    if (audio_backend::simd::cpu_supports(audio_backend::simd::CPUFeature::AVX512F))
        std::cout << "  AVX-512支持" << std::endl;
    if (audio_backend::simd::cpu_supports(audio_backend::simd::CPUFeature::NEON))
        std::cout << "  NEON支持" << std::endl;
    
    std::cout << "最高SIMD级别";
    switch (audio_backend::simd::get_max_simd_level()) {
        case audio_backend::simd::SIMDLevel::NONE: std::cout << "无SIMD支持"; break;
        case audio_backend::simd::SIMDLevel::SSE: std::cout << "SSE"; break;
        case audio_backend::simd::SIMDLevel::SSE3: std::cout << "SSE3"; break;
        case audio_backend::simd::SIMDLevel::SSE4: std::cout << "SSE4"; break;
        case audio_backend::simd::SIMDLevel::AVX: std::cout << "AVX"; break;
        case audio_backend::simd::SIMDLevel::AVX2: std::cout << "AVX2"; break;
        case audio_backend::simd::SIMDLevel::AVX512: std::cout << "AVX-512"; break;
        case audio_backend::simd::SIMDLevel::NEON: std::cout << "NEON"; break;
        case audio_backend::simd::SIMDLevel::NEON_FP16: std::cout << "NEON FP16"; break;
    }
    std::cout << std::endl;
    
    std::cout << "推荐SIMD级别";
    switch (audio_backend::simd::get_recommended_simd_level()) {
        case audio_backend::simd::SIMDLevel::NONE: std::cout << "无SIMD支持"; break;
        case audio_backend::simd::SIMDLevel::SSE: std::cout << "SSE"; break;
        case audio_backend::simd::SIMDLevel::SSE3: std::cout << "SSE3"; break;
        case audio_backend::simd::SIMDLevel::SSE4: std::cout << "SSE4"; break;
        case audio_backend::simd::SIMDLevel::AVX: std::cout << "AVX"; break;
        case audio_backend::simd::SIMDLevel::AVX2: std::cout << "AVX2"; break;
        case audio_backend::simd::SIMDLevel::AVX512: std::cout << "AVX-512"; break;
        case audio_backend::simd::SIMDLevel::NEON: std::cout << "NEON"; break;
        case audio_backend::simd::SIMDLevel::NEON_FP16: std::cout << "NEON FP16"; break;
    }
    std::cout << std::endl;
}

内存对齐

对齐要求

SIMD指令通常要求数据按特定字节边界对齐以获得最佳性能

  • SSE指令16字节对齐
  • AVX指令32字节对齐
  • AVX-512指令64字节对齐

系统定义了以下对齐常量:

constexpr size_t ALIGNMENT_SSE = 16;      // SSE需要16字节对齐
constexpr size_t ALIGNMENT_AVX = 32;      // AVX需要32字节对齐
constexpr size_t ALIGNMENT_AVX512 = 64;   // AVX-512需要64字节对齐
constexpr size_t ALIGNMENT_CACHE = 64;    // CPU缓存行大小通常64字节

未对齐的内存访问会导致以下问题:

  1. 性能下降:某处理器上未对齐访问会导致额外的内存事务
  2. 崩溃风险某些SIMD指令要求严格对齐未对齐可能导致异常
  3. 分支指令:编译器可能插入额外的分支代码检查对齐,降低性能

对齐分配器

系统提供了AlignedAllocator模板类可用于STL容器

template<typename T, size_t Alignment = ALIGNMENT_AVX>
class AlignedAllocator {
    // 标准分配器接口
};

// 便捷类型定义
template<typename T>
using AlignedVector16 = std::vector<T, AlignedAllocator<T, ALIGNMENT_SSE>>;

template<typename T>
using AlignedVector32 = std::vector<T, AlignedAllocator<T, ALIGNMENT_AVX>>;

template<typename T>
using AlignedVector64 = std::vector<T, AlignedAllocator<T, ALIGNMENT_AVX512>>;

// 根据当前CPU支持的最高SIMD级别选择对齐方式
template<typename T>
using AlignedVectorAuto = std::vector<T, AlignedAllocator<T, ALIGNMENT_AVX>>;

使用示例:

// 创建按32字节对齐的float向量
audio_backend::simd::AlignedVector32<float> aligned_data(1024);

// 验证对齐
if (audio_backend::simd::is_aligned<audio_backend::simd::ALIGNMENT_AVX>(aligned_data.data())) {
    std::cout << "数据已按AVX要求对齐" << std::endl;
}

// 使用向量
for (size_t i = 0; i < aligned_data.size(); ++i) {
    aligned_data[i] = static_cast<float>(i);
}

对齐缓冲区

系统还提供了AlignedBuffer适用于需要RAII语义的场景

template<typename T, size_t Alignment = ALIGNMENT_AVX>
class AlignedBuffer {
public:
    AlignedBuffer();
    explicit AlignedBuffer(size_t count);
    ~AlignedBuffer();
    
    // 内存管理
    void allocate(size_t count);
    void deallocate();
    void resize(size_t new_count);
    
    // 访问接口
    T* data() noexcept;
    const T* data() const noexcept;
    
    // 元素访问
    T& operator[](size_t index) noexcept;
    const T& operator[](size_t index) const noexcept;
    
    // 迭代器支持
    T* begin() noexcept;
    T* end() noexcept;
    const T* begin() const noexcept;
    const T* end() const noexcept;
    
    // 状态查询
    size_t size() const noexcept;
    bool empty() const noexcept;
    bool is_properly_aligned() const noexcept;
};

使用示例:

// 创建一个按32字节对齐的包含1024个float的缓冲区
audio_backend::simd::AlignedBuffer<float, audio_backend::simd::ALIGNMENT_AVX> buffer(1024);

// 填充数据
for (size_t i = 0; i < buffer.size(); ++i) {
    buffer[i] = static_cast<float>(i);
}

// 验证对齐
if (buffer.is_properly_aligned()) {
    std::cout << "缓冲区已正确对齐" << std::endl;
}

// 重新分配大小
buffer.resize(2048);

函数分发器

多版本函数

函数分发器是SIMD优化系统的核心它允许为同一函数提供多个不同SIMD指令集的实现版本并在运行时自动选择最优版本

enum class FunctionVersion {
    SCALAR = 0,     // 标量实现(默认回退)
    SSE,            // SSE实现  
    SSE3,           // SSE3实现
    SSE4,           // SSE4实现
    AVX,            // AVX实现
    AVX2,           // AVX2实现
    AVX512,         // AVX-512实现
    NEON,           // ARM NEON实现
    NEON_FP16,      // ARM NEON FP16实现
    
    VERSION_COUNT   // 版本数量(用于数组大小)
};

template<typename ReturnType, typename... Args>
class MultiVersionFunction<ReturnType(Args...)> {
public:
    // 注册函数版本
    void register_version(FunctionVersion version, FunctionType function);
    
    // 获取最佳函数版本
    const FunctionType& get_best_function() const;
    
    // 调用最佳函数版本
    ReturnType operator()(Args... args) const;
};

自动分发

函数分发器使用单例模式,提供全局访问点:

class FunctionDispatcher {
public:
    // 获取单例实例
    static FunctionDispatcher& instance();
    
    // 注册函数
    template<typename FuncSignature>
    void register_function(const std::string& name, 
                          FunctionVersion version, 
                          std::function<FuncSignature> function);
    
    // 获取函数
    template<typename FuncSignature>
    const MultiVersionFunction<FuncSignature>& get_function(const std::string& name);
    
    // 调用函数
    template<typename FuncSignature, typename... Args>
    auto call_function(const std::string& name, Args&&... args);
    
    // 列出所有已注册的函数
    std::vector<std::string> list_functions() const;
    
    // 打印函数注册状态
    void print_registry_status() const;
};

注册机制

系统提供了便捷的宏来注册和使用SIMD函数

// 注册函数版本的宏
#define REGISTER_SIMD_FUNCTION(name, version, function) \
    audio_backend::simd::FunctionDispatcher::instance().register_function<decltype(function)>(name, version, function)

// 获取函数的宏
#define GET_SIMD_FUNCTION(signature, name) \
    audio_backend::simd::FunctionDispatcher::instance().get_function<signature>(name)

// 调用函数的宏
#define CALL_SIMD_FUNCTION(signature, name, ...) \
    audio_backend::simd::FunctionDispatcher::instance().call_function<signature>(name, __VA_ARGS__)

// 调用音频函数的便捷宏
#define CALL_SIMD_AUDIO_FUNCTION(name, ...) \
    CALL_SIMD_FUNCTION(decltype(name), #name, __VA_ARGS__)

函数注册示例:

// 标量版本(总是提供作为回退)
void mix_audio_f32_scalar(const float* input1, const float* input2, float* output, size_t samples) {
    for (size_t i = 0; i < samples; ++i) {
        output[i] = input1[i] + input2[i];
    }
}
REGISTER_SIMD_FUNCTION("mix_audio_f32", FunctionVersion::SCALAR, mix_audio_f32_scalar);

// SSE版本
#ifdef AUDIO_BACKEND_ENABLE_SSE
void mix_audio_f32_sse(const float* input1, const float* input2, float* output, size_t samples) {
    // 使用SSE指令实现
    // ...
}
REGISTER_SIMD_FUNCTION("mix_audio_f32", FunctionVersion::SSE, mix_audio_f32_sse);
#endif

// AVX版本
#ifdef AUDIO_BACKEND_ENABLE_AVX
void mix_audio_f32_avx(const float* input1, const float* input2, float* output, size_t samples) {
    // 使用AVX指令实现
    // ...
}
REGISTER_SIMD_FUNCTION("mix_audio_f32", FunctionVersion::AVX, mix_audio_f32_avx);
#endif

// AVX2版本
#ifdef AUDIO_BACKEND_ENABLE_AVX2
void mix_audio_f32_avx2(const float* input1, const float* input2, float* output, size_t samples) {
    // 使用AVX2指令实现
    // ...
}
REGISTER_SIMD_FUNCTION("mix_audio_f32", FunctionVersion::AVX2, mix_audio_f32_avx2);
#endif

// ARM NEON版本
#ifdef AUDIO_BACKEND_ENABLE_NEON
void mix_audio_f32_neon(const float* input1, const float* input2, float* output, size_t samples) {
    // 使用NEON指令实现
    // ...
}
REGISTER_SIMD_FUNCTION("mix_audio_f32", FunctionVersion::NEON, mix_audio_f32_neon);
#endif

音频处理函数

音频后端系统提供了多种SIMD优化的音频处理函数

格式转换

// 16位整数转32位浮点数
void convert_i16_to_f32(const int16_t* input, float* output, size_t samples);

// 32位浮点数转16位整数
void convert_f32_to_i16(const float* input, int16_t* output, size_t samples);

// 32位整数转32位浮点数
void convert_i32_to_f32(const int32_t* input, float* output, size_t samples);

// 32位浮点数转32位整数
void convert_f32_to_i32(const float* input, int32_t* output, size_t samples);

// 单声道转立体声(复制)
void mono_to_stereo_f32(const float* input, float* output, size_t samples);

// 立体声转单声道(平均)
void stereo_to_mono_f32(const float* input, float* output, size_t samples);

使用示例:

// 加载16位WAV文件数据并转换为32位浮点数
void convert_wav_to_float(const int16_t* wav_data, size_t sample_count, float* output) {
    // 使用SIMD优化的转换函数
    audio_backend::simd::convert_i16_to_f32(wav_data, output, sample_count);
}

音量控制

// 应用恒定音量倍数
void apply_gain_f32(const float* input, float gain, float* output, size_t samples);

// 应用渐变音量(线性插值)
void apply_gain_ramp_f32(const float* input, float start_gain, float end_gain, 
                        float* output, size_t samples);

// 应用每个样本不同的音量
void apply_gain_per_sample_f32(const float* input, const float* gains, 
                              float* output, size_t samples);

使用示例:

// 应用淡入效果
void fade_in(float* audio_buffer, size_t samples, float duration_seconds, float sample_rate) {
    float* temp_buffer = new float[samples];
    memcpy(temp_buffer, audio_buffer, samples * sizeof(float));
    
    // 使用SIMD优化的音量渐变函数
    audio_backend::simd::apply_gain_ramp_f32(temp_buffer, 0.0f, 1.0f, audio_buffer, samples);
    
    delete[] temp_buffer;
}

音频混合

// 混合两个浮点音频缓冲区
void mix_audio_f32(const float* input1, const float* input2, float* output, size_t samples);

// 混合多个浮点音频缓冲区
void mix_audio_multi_f32(const float* const* inputs, size_t num_inputs, float* output, size_t samples);

// 带权重的音频混合
void mix_audio_weighted_f32(const float* input1, float weight1, 
                           const float* input2, float weight2, 
                           float* output, size_t samples);

使用示例:

// 混合多个音频轨道
void mix_tracks(const std::vector<float*>& tracks, size_t track_samples, float* output) {
    // 创建轨道指针数组
    std::vector<const float*> track_ptrs;
    for (auto track : tracks) {
        track_ptrs.push_back(track);
    }
    
    // 使用SIMD优化的多轨混音函数
    audio_backend::simd::mix_audio_multi_f32(track_ptrs.data(), track_ptrs.size(), 
                                            output, track_samples);
}

数学运算

// 向量加法
void vector_add_f32(const float* a, const float* b, float* result, size_t samples);

// 向量减法
void vector_subtract_f32(const float* a, const float* b, float* result, size_t samples);

// 向量乘法
void vector_multiply_f32(const float* a, const float* b, float* result, size_t samples);

// 标量乘法
void vector_scale_f32(const float* input, float scale, float* output, size_t samples);

// 计算RMS均方根
float calculate_rms_f32(const float* input, size_t samples);

// 计算峰值
float calculate_peak_f32(const float* input, size_t samples);

使用示例:

// 计算音频电平
void calculate_audio_levels(const float* audio_data, size_t samples, float* rms_level, float* peak_level) {
    // 使用SIMD优化的RMS和峰值计算
    *rms_level = audio_backend::simd::calculate_rms_f32(audio_data, samples);
    *peak_level = audio_backend::simd::calculate_peak_f32(audio_data, samples);
    
    // 转换为dB
    *rms_level = 20.0f * log10f(*rms_level + 1e-6f);
    *peak_level = 20.0f * log10f(*peak_level + 1e-6f);
}

音频分析

// 检测静音
bool detect_silence_f32(const float* input, size_t samples, float threshold = -60.0f);

// 检测削波
bool detect_clipping_f32(const float* input, size_t samples, float threshold = 0.99f);

// 计算频谱能量需要配合FFT使用
void calculate_spectral_energy_f32(const float* fft_output, float* energy_bands, 
                                  size_t fft_size, size_t num_bands);

使用示例:

// 音频质量监控
bool check_audio_quality(const float* audio_data, size_t samples) {
    // 检查是否有削波
    bool has_clipping = audio_backend::simd::detect_clipping_f32(audio_data, samples);
    
    // 检查是否为静音
    bool is_silent = audio_backend::simd::detect_silence_f32(audio_data, samples);
    
    if (has_clipping) {
        std::cout << "警告:检测到音频削波!" << std::endl;
    }
    
    if (is_silent) {
        std::cout << "警告:检测到音频静音!" << std::endl;
    }
    
    return !has_clipping && !is_silent;
}

使用示例

基本示例

以下是使用SIMD优化函数的基本示例

#include "simd/audio_processing.h"
#include <iostream>
#include <vector>

int main() {
    // 初始化音频处理注册表确保所有SIMD函数版本已注册
    audio_backend::simd::AudioProcessingRegistry::register_all_functions();
    
    // 打印CPU信息
    auto& cpu_info = audio_backend::simd::get_cpu_info();
    std::cout << "CPU: " << cpu_info.brand << std::endl;
    std::cout << "最高SIMD级别: " << 
        audio_backend::simd::function_version_to_string(
            audio_backend::simd::simd_level_to_version(cpu_info.max_simd_level)
        ) << std::endl;
    
    // 创建对齐的音频缓冲区
    constexpr size_t samples = 1024;
    audio_backend::simd::AlignedBuffer<float> input1(samples);
    audio_backend::simd::AlignedBuffer<float> input2(samples);
    audio_backend::simd::AlignedBuffer<float> output(samples);
    
    // 填充输入缓冲区
    for (size_t i = 0; i < samples; ++i) {
        input1[i] = static_cast<float>(i) / samples;  // 斜坡
        input2[i] = 0.5f * sinf(static_cast<float>(i) * 0.1f);  // 正弦
    }
    
    // 使用SIMD函数
    audio_backend::simd::mix_audio_f32(input1.data(), input2.data(), output.data(), samples);
    
    std::cout << "前10个混合结果" << std::endl;
    for (size_t i = 0; i < 10; ++i) {
        std::cout << output[i] << " ";
    }
    std::cout << std::endl;
    
    // 计算音量统计
    float rms = audio_backend::simd::calculate_rms_f32(output.data(), samples);
    float peak = audio_backend::simd::calculate_peak_f32(output.data(), samples);
    
    std::cout << "RMS: " << rms << std::endl;
    std::cout << "Peak: " << peak << std::endl;
    
    return 0;
}

音频处理示例

以下是一个更复杂的音频处理示例展示了如何使用SIMD优化函数处理音频数据

#include "simd/audio_processing.h"
#include <iostream>
#include <vector>
#include <chrono>

// 简单的音频处理链
void process_audio_chain(const float* input, float* output, size_t samples) {
    // 创建临时缓冲区
    audio_backend::simd::AlignedBuffer<float> temp1(samples);
    audio_backend::simd::AlignedBuffer<float> temp2(samples);
    
    // 阶段1应用增益音量控制
    audio_backend::simd::apply_gain_f32(input, 0.8f, temp1.data(), samples);
    
    // 阶段2低通滤波
    float state = 0.0f;
    audio_backend::simd::lowpass_filter_f32(temp1.data(), temp2.data(), samples, 
                                          1000.0f, 44100.0f, &state);
    
    // 阶段3添加延迟果
    constexpr size_t delay_samples = 4410;  // 约100ms @ 44.1kHz
    audio_backend::simd::AlignedBuffer<float> delay_buffer(delay_samples);
    float delay_index = 0.0f;
    audio_backend::simd::delay_effect_f32(temp2.data(), output, samples,
                                        delay_buffer.data(), delay_samples,
                                        delay_samples, 0.3f, &delay_index);
}

int main() {
    // 初始化音频处理注册表
    audio_backend::simd::AudioProcessingRegistry::register_all_functions();
    
    // 创建测试音频数据1秒44.1kHz
    constexpr size_t samples = 44100;
    audio_backend::simd::AlignedBuffer<float> input(samples);
    audio_backend::simd::AlignedBuffer<float> output(samples);
    
    // 生成测试信号440Hz正弦波
    for (size_t i = 0; i < samples; ++i) {
        input[i] = 0.5f * sinf(2.0f * 3.14159f * 440.0f * i / 44100.0f);
    }
    
    // 测量处理时间
    auto start = std::chrono::high_resolution_clock::now();
    
    // 处理音频
    process_audio_chain(input.data(), output.data(), samples);
    
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    
    std::cout << "处理1秒音频用时: " << duration.count() / 1000.0 << " ms" << std::endl;
    
    // 计算处理后的音频统计
    float input_rms = audio_backend::simd::calculate_rms_f32(input.data(), samples);
    float output_rms = audio_backend::simd::calculate_rms_f32(output.data(), samples);
    
    std::cout << "输入RMS: " << input_rms << std::endl;
    std::cout << "输出RMS: " << output_rms << std::endl;
    
    // 检测削波
    bool has_clipping = audio_backend::simd::detect_clipping_f32(output.data(), samples);
    std::cout << "输出削波检测: " << (has_clipping ? "是" : "否") << std::endl;
    
    return 0;
}

性能对比

以下示例对比了不同SIMD指令集实现的性能差异

#include "simd/audio_processing.h"
#include "simd/function_dispatcher.h"
#include <iostream>
#include <vector>
#include <chrono>
#include <iomanip>

// 标量实现无SIMD
void mix_audio_scalar(const float* input1, const float* input2, float* output, size_t samples) {
    for (size_t i = 0; i < samples; ++i) {
        output[i] = input1[i] + input2[i];
    }
}

// 测量函数执行时间(微秒)
template<typename Func, typename... Args>
double measure_execution_time(Func&& func, Args&&... args) {
    constexpr int iterations = 100;
    
    auto start = std::chrono::high_resolution_clock::now();
    
    for (int i = 0; i < iterations; ++i) {
        func(std::forward<Args>(args)...);
    }
    
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    
    return static_cast<double>(duration.count()) / iterations;
}

int main() {
    // 初始化音频处理注册表
    audio_backend::simd::AudioProcessingRegistry::register_all_functions();
    
    // 打印可用的SIMD函数版本
    audio_backend::simd::FunctionDispatcher::instance().print_registry_status();
    
    // 创建测试数据8MB音频数据
    constexpr size_t samples = 2 * 1024 * 1024;
    audio_backend::simd::AlignedBuffer<float, audio_backend::simd::ALIGNMENT_AVX512> input1(samples);
    audio_backend::simd::AlignedBuffer<float, audio_backend::simd::ALIGNMENT_AVX512> input2(samples);
    audio_backend::simd::AlignedBuffer<float, audio_backend::simd::ALIGNMENT_AVX512> output(samples);
    
    // 填充测试数据
    for (size_t i = 0; i < samples; ++i) {
        input1[i] = static_cast<float>(i % 1024) / 1024.0f;
        input2[i] = static_cast<float>((1024 - i % 1024)) / 1024.0f;
    }
    
    // 获取不同SIMD版本的函数
    using MixFunctionType = void (*)(const float*, const float*, float*, size_t);
    
    auto& function_dispatcher = audio_backend::simd::FunctionDispatcher::instance();
    auto& mix_function = function_dispatcher.get_function<MixFunctionType>("mix_audio_f32");
    
    // 打印性能对比表头
    std::cout << std::left << std::setw(12) << "实现版本"
              << std::setw(15) << "执行时间(μs)"
              << std::setw(10) << "相对加速" << std::endl;
    std::cout << "---------------------------------------" << std::endl;
    
    // 测量标量版本(基准)
    double scalar_time = measure_execution_time(mix_audio_scalar,
                                              input1.data(), input2.data(), output.data(), samples);
    
    std::cout << std::left << std::setw(12) << "标量"
              << std::setw(15) << std::fixed << std::setprecision(2) << scalar_time
              << std::setw(10) << "1.00x" << std::endl;
    
    // 测量可用的SIMD版本
    auto available_versions = mix_function.get_available_versions();
    for (auto version : available_versions) {
        if (version == audio_backend::simd::FunctionVersion::SCALAR) continue;
        
        // 注册临时函数,使其直接使用特定版本
        auto& temp_function = function_dispatcher.get_function<MixFunctionType>("temp_mix_function");
        temp_function.register_version(audio_backend::simd::FunctionVersion::SCALAR, 
                                       mix_function.get_best_function());
        
        double version_time = measure_execution_time(
            [&](const float* a, const float* b, float* c, size_t n) {
                CALL_SIMD_FUNCTION(MixFunctionType, "temp_mix_function", a, b, c, n);
            },
            input1.data(), input2.data(), output.data(), samples
        );
        
        double speedup = scalar_time / version_time;
        
        std::cout << std::left << std::setw(12) 
                  << audio_backend::simd::function_version_to_string(version)
                  << std::setw(15) << std::fixed << std::setprecision(2) << version_time
                  << std::setw(10) << std::fixed << std::setprecision(2) << speedup << "x" << std::endl;
    }
    
    // 测量自动选择版本
    double auto_time = measure_execution_time(
        [&](const float* a, const float* b, float* c, size_t n) {
            CALL_SIMD_FUNCTION(MixFunctionType, "mix_audio_f32", a, b, c, n);
        },
        input1.data(), input2.data(), output.data(), samples
    );
    
    double auto_speedup = scalar_time / auto_time;
    
    std::cout << std::left << std::setw(12) << "自动选择"
              << std::setw(15) << std::fixed << std::setprecision(2) << auto_time
              << std::setw(10) << std::fixed << std::setprecision(2) << auto_speedup << "x" << std::endl;
    
    return 0;
}

指令集特定优化

SSE优化

SSEStreaming SIMD Extensions是x86架构的128位SIMD指令集支持同时处理4个单精度浮点数

// SSE优化的音频混合
void mix_audio_f32_sse(const float* input1, const float* input2, float* output, size_t samples) {
    // 确保内存对齐
    assert(audio_backend::simd::is_aligned<16>(input1));
    assert(audio_backend::simd::is_aligned<16>(input2));
    assert(audio_backend::simd::is_aligned<16>(output));
    
    // 按4个浮点数一组处理
    size_t i = 0;
    size_t vector_size = samples & ~3ULL;  // 向下取整为4的倍数
    
    // SSE向量化循环
    for (; i < vector_size; i += 4) {
        __m128 a = _mm_load_ps(input1 + i);
        __m128 b = _mm_load_ps(input2 + i);
        __m128 sum = _mm_add_ps(a, b);
        _mm_store_ps(output + i, sum);
    }
    
    // 处理剩余样本
    for (; i < samples; ++i) {
        output[i] = input1[i] + input2[i];
    }
}

AVX优化

AVXAdvanced Vector Extensions是x86架构的256位SIMD指令集支持同时处理8个单精度浮点数

// AVX优化的音频混合
void mix_audio_f32_avx(const float* input1, const float* input2, float* output, size_t samples) {
    // 确保内存对齐
    assert(audio_backend::simd::is_aligned<32>(input1));
    assert(audio_backend::simd::is_aligned<32>(input2));
    assert(audio_backend::simd::is_aligned<32>(output));
    
    // 按8个浮点数一组处理
    size_t i = 0;
    size_t vector_size = samples & ~7ULL;  // 向下取整为8的倍数
    
    // AVX向量化循环
    for (; i < vector_size; i += 8) {
        __m256 a = _mm256_load_ps(input1 + i);
        __m256 b = _mm256_load_ps(input2 + i);
        __m256 sum = _mm256_add_ps(a, b);
        _mm256_store_ps(output + i, sum);
    }
    
    // 处理剩余样本
    for (; i < samples; ++i) {
        output[i] = input1[i] + input2[i];
    }
}

ARM NEON优化

NEON是ARM架构的SIMD指令集支持同时处理4个单精度浮点数

// ARM NEON优化的音频混合
void mix_audio_f32_neon(const float* input1, const float* input2, float* output, size_t samples) {
    // 按4个浮点数一组处理
    size_t i = 0;
    size_t vector_size = samples & ~3ULL;  // 向下取整为4的倍数
    
    // NEON向量化循环
    for (; i < vector_size; i += 4) {
        float32x4_t a = vld1q_f32(input1 + i);
        float32x4_t b = vld1q_f32(input2 + i);
        float32x4_t sum = vaddq_f32(a, b);
        vst1q_f32(output + i, sum);
    }
    
    // 处理剩余样本
    for (; i < samples; ++i) {
        output[i] = input1[i] + input2[i];
    }
}

最佳实践

性能优化技巧

  1. 内存对齐

    • 总是使用对齐的内存分配器
    • 避免不对齐的内存访问
    • 可能的情况下使用自动对齐的数据结构
  2. 数据布局

    • 优先使用结构数组SoA而非数组结构AoS
    • 将经常一起处理的数据放在连续内存中
    • 考虑缓存行大小通常64字节
  3. 分支避免

    • 避免在SIMD代码中使用条件分支
    • 使用掩码和选择指令代替分支
    • 考虑预测分支的成本
  4. 循环优化

    • 展开循环以减少循环开销
    • 使用预取指令提前加载数据
    • 考虑向量长度和处理批量大小

跨平台考虑

  1. 功能检测

    • 始终在运行时检测CPU特性
    • 为所有指令集提供回退实现
    • 使用函数分发器自动选择最佳实现
  2. 平台差异

    • x86和ARM架构有不同的内存对齐要求
    • 不同编译器有不同的SIMD内联汇编支持
    • 考虑不同平台的Cache大小和特性
  3. 编译器支持

    • 使用条件编译分离不同SIMD实现
    • 根据目标平台设置适当的编译器标志
    • 考虑使用自动矢量化作为补充