使用加速框架,没有可观察到的加速

Posted

技术标签:

【中文标题】使用加速框架,没有可观察到的加速【英文标题】:Accelerate framework used, no observable speedup 【发布时间】:2015-02-26 01:07:55 【问题描述】:

我有以下一段音频代码,我认为它非常适合在加速框架中使用 vDSP。

// --- get pointers for buffer lists
float* left = (float*)audio->mBuffers[0].mData;
float* right = numChans == 2 ? (float*)audio->mBuffers[1].mData : NULL;

float dLeftAccum = 0.0;
float dRightAccum = 0.0;

float fMix = 0.25; // -12dB HR per note

// --- the frame processing loop
for(UInt32 frame=0; frame<inNumberFrames; ++frame)

    // --- zero out for each trip through loop
    dLeftAccum = 0.0;
    dRightAccum = 0.0;
    float dLeft = 0.0;
    float dRight = 0.0;

    // --- synthesize and accumulate each note's sample
    for(int i=0; i<MAX_VOICES; i++)
    
        // --- render
        if(m_pVoiceArray[i]) 
            m_pVoiceArray[i]->doVoice(dLeft, dRight);

        // --- accumulate and scale
        dLeftAccum += fMix*(float)dLeft;
        dRightAccum += fMix*(float)dRight;

    

    // --- accumulate in output buffers
    // --- mono
    left[frame] = (float)dLeftAccum;

    // --- stereo
    if(right) right[frame] = (float)dRightAccum;


// needed???
//  mAbsoluteSampleFrame += inNumberFrames;

return noErr;

因此我修改它以使用 vDSP,在帧块的末尾乘以 fMix。

// --- the frame processing loop
for(UInt32 frame=0; frame<inNumberFrames; ++frame)

    // --- zero out for each trip through loop
    dLeftAccum = 0.0;
    dRightAccum = 0.0;
    float dLeft = 0.0;
    float dRight = 0.0;

    // --- synthesize and accumulate each note's sample
    for(int i=0; i<MAX_VOICES; i++)
    
        // --- render
        if(m_pVoiceArray[i]) 
            m_pVoiceArray[i]->doVoice(dLeft, dRight);

        // --- accumulate and scale
        dLeftAccum += (float)dLeft;
        dRightAccum += (float)dRight;

    

    // --- accumulate in output buffers
    // --- mono
    left[frame] = (float)dLeftAccum;

    // --- stereo
    if(right) right[frame] = (float)dRightAccum;

vDSP_vsmul(left, 1, &fMix, left, 1, inNumberFrames);
vDSP_vsmul(right, 1, &fMix, right, 1, inNumberFrames);
// needed???
//  mAbsoluteSampleFrame += inNumberFrames;

return noErr;

但是,我的 CPU 使用率仍然保持不变。 我认为在这里使用 vDSP 没有明显的好处。 我这样做正确吗?非常感谢。

对向量运算还是个新手,请放轻松 :)

如果我应该做一些明显的优化(加速框架之外),请随时向我指出,谢谢!

【问题讨论】:

这里假设 m_pVoiceArray[i]->doVoice(dLeft, dRight);正在修改 dLeft 和 dRight (因为它们是通过引用传递的,这是 C++?)我会让 doVoice 函数一次产生一堆样本,而不仅仅是一个。您可能大部分时间都花在开销查找数据和进行函数调用上。也就是说,反转帧处理循环中的循环顺序。否则,我想向您介绍我的朋友乘法运算符。 是的,它们是通过引用传递的,C++。 可能它并没有加快多少,因为每个样本的大部分时间都花在了 MAX_VOICES 循环中。您可以通过查看 Instruments 中每行源代码的时间使用情况来验证这一点。与每个(样本 * 语音)调用函数指针的成本相比,像您从循环中拉出的乘法是微不足道的。 是的,我一直在这样做,因为...正如你所说,在某些地方可以将计算从主处理循环中提取出来,或者减少计算频率。 【参考方案1】:

您的矢量调用正在以音频采样率对每个样本执行 2 次乘法。如果您的采样率为 192kHz,那么您只是在谈论每秒 384000 次乘法 - 不足以在现代 CPU 上注册。此外,您正在移动现有乘法到另一个地方。如果您查看生成的程序集,我会猜想编译器相当不错地优化了您的原始代码,并且 vDSP 调用中的任何加速都将被您需要第二个循环的事实所抵消。

另一个需要注意的重要事项是,当矢量数据在 16 字节边界上对齐时,所有 vDSP 函数都会更好地工作。如果您查看 SSE2 指令集(我确信 vDSP 大量使用),您会发现许多指令都有一个用于对齐数据的版本和另一个用于未对齐数据的版本。

在 gcc 中对齐数据的方式是这样的:

float inVector[8] = 1, 2, 3, 4, 5, 6, 7, 8 __attribute__ ((aligned(16)));

或者,如果您在堆上分配,请查看aligned_malloc 是否可用。

【讨论】:

以上是关于使用加速框架,没有可观察到的加速的主要内容,如果未能解决你的问题,请参考以下文章

使用加速框架的矩阵乘法和逆问题

在音频合成方面使用 vDSP(加速框架)

使用多处理池在 python 中加速 TFLite 推理

优化CSS并加速网站的21种方法

加速tensorflowjs模型

加速框架 iOS - FFT 输入