2015-02-26 2 views
1

У меня есть следующий фрагмент аудиокода, который, как я думал, был бы хорошим кандидатом для использования 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; 

Однако мое использование ЦП по-прежнему остается неизменным. Я не вижу ощутимой выгоды от использования vDSP здесь. Я делаю это правильно? Большое спасибо.

Еще новый для векторных операций, легко идти на меня :)

Если есть некоторые очевидные оптимизации, что я должен делать (вне рамок ускорения), не стесняйтесь указать на это мне, спасибо!

+0

Предполагая, что m_pVoiceArray [i] -> doVoice (dLeft, dRight); изменяет dLeft и dRight (потому что они передаются по ссылке, и это C++?) Я бы хотел, чтобы функция doVoice создавала кучу образцов одновременно, а не только одну. Вероятно, вы тратите большую часть времени на накладные расходы, просматривая данные и делая вызовы функций. То есть, измените порядок циклов в цикле обработки кадров. В противном случае я хотел бы познакомить вас с моим другом оператором multiply. –

+0

Да, они передаются по ссылке, C++. – lppier

+0

Вероятно, это не ускорилось, потому что большая часть вашего времени на выборку была потрачена в цикле MAX_VOICES. Вы можете проверить это, посмотрев время использования на строку источника в Инструментах. Несколько размножений, как то, что вы вышли из цикла, тривиально по сравнению со стоимостью вызова указателя функции на (образец * голос). –

ответ

1

Вы - векторный вызов, выполняющий 2 умножения на выборку с частотой выборки аудио. Если ваша частота дискретизации составляла 192 кГц, вы говорите только о 384000 умножениях в секунду - этого недостаточно для регистрации на современном процессоре. Кроме того, вы находитесь , перемещая существующие множители в другое место. Если бы вы взглянули на сгенерированную сборку, я бы догадался, что компилятор оптимизировал ваш оригинальный код довольно прилично, и любая скорость в вызове vDSP будет компенсирована тем фактом, что вам требуется второй цикл.

Еще одна важная вещь, которую следует отметить, заключается в том, что все функции vDSP будут работать лучше, когда векторные данные будут выровнены по 16-байтовой границе. Если вы посмотрите на набор инструкций SSE2 (что я уверен, что vDSP использует сильно), вы увидите, что во многих инструкциях есть версия для выровненных данных и другая версия для неуравновешенных данных.

, как вы бы выровнять данные в GCC-то вроде этого:

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

Или, если вы выделения на куче взгляд, если aligned_malloc доступен.

Смежные вопросы