2013-06-10 3 views
2

Рассмотрим следующие два фрагмента кода, первый вариант C:ARM вопрос производительности неон

void __attribute__((no_inline)) proj(uint8_t * line, uint16_t length) 
{ 
    uint16_t i; 
    int16_t tmp; 
    for(i=HPHD_MARGIN; i<length-HPHD_MARGIN; i++) { 
     tmp = line[i-3] - 4*line[i-2] + 5*line[i-1] - 5*line[i+1] + 4*line[i+2] - line[i+3]; 
     hphd_temp[i]=ABS(tmp); 
    } 
} 

Вторая такая же функция (за границей, за исключением) с использованием неоновых встроенных функций

void __attribute__((no_inline)) proj_neon(uint8_t * line, uint16_t length) 
{ 
    int i; 
    uint8x8_t b0b7, b8b15, p1p8,p2p9,p4p11,p5p12,p6p13, m4, m5; 
    uint16x8_t result; 

    m4 = vdup_n_u8(4); 
    m5 = vdup_n_u8(5); 
    b0b7 = vld1_u8(line); 
    for(i = 0; i < length - 16; i+=8) { 
     b8b15 = vld1_u8(line + i + 8); 
     p1p8 = vext_u8(b0b7,b8b15, 1); 
     p2p9 = vext_u8(b0b7,b8b15, 2); 
     p4p11 = vext_u8(b0b7,b8b15, 4); 
     p5p12 = vext_u8(b0b7,b8b15, 5); 
     p6p13 = vext_u8(b0b7,b8b15, 6); 

     result = vsubl_u8(b0b7, p6p13); //p[-3] 
     result = vmlal_u8(result, p2p9, m5); // +5 * p[-1]; 
     result = vmlal_u8(result, p5p12, m4);// +4 * p[1]; 
     result = vmlsl_u8(result, p1p8, m4); //-4 * p[-2]; 
     result = vmlsl_u8(result, p4p11, m5);// -5 * p[1]; 
     vst1q_s16(hphd_temp + i + 3, vabsq_s16(vreinterpretq_s16_u16(result))); 
     b0b7 = b8b15; 
    } 
    /* todo : remaining pixel */ 

} 

Я разочарован приростом производительности: это около 10 - 15%. Если я смотрю на сгенерированную сборке:

  • C версия преобразуется в петле на 108 команд
  • Неон версии преобразуется в цикле с 72 команд.

Но одна петля в неоновом коде вычисляет в 8 раз больше данных, чем итерация по петле C, поэтому следует увидеть значительное улучшение.

Есть ли у вас какие-либо объяснения относительно небольшой разницы между двумя версиями?

Дополнительная информация: Данные испытаний - изображение 10 Мпикс, время вычисления составляет около 2 секунд для версии C.

Процессор: ARM Cortex A8

+0

Нередко наблюдается меньший прирост производительности, чем ожидалось, когда вы говорите о подсчетах команд, против времени выполнения. Особенно при работе с большими объемами данных, например изображениями. Вполне вероятно, что, несмотря на то, что вы потеряли 36 инструкций, большую часть времени вы ждете, когда вещи будут перемещаться в памяти, и что даже с такой разницей в инструкциях большая часть вашего повышения производительности поступает из памяти обработки неоновых кодов лучше (прогнозирование ветвей, большие куски на петлю, меньшее количество инструкций и т. д.), чем от количества выполненных инструкций. – ChrisCM

+0

Какие параметры компилятора, компилятора и командной строки вы используете? Не могли бы вы включить разбор встроенной версии? – unixsmurf

+0

@ChrisCM: Это не около 108 против 72, но 108 * 8 против 72. Даже учитывая двойную проблему, я все еще мог ожидать улучшения в 6 раз. – shodanex

ответ

4

Я собираюсь принять диких угадать и сказать, что кэширование (данные) по этой причине вы не видите большой производительности получить вы ожидаете. Хотя я не знаю, поддерживает ли ваш чипсет кеширование или на каком уровне, если данные охватывают линии кэша, имеет плохое выравнивание или работает в среде, где центральный процессор делает другие вещи одновременно (прерывания, потоки и т. Д. .), то это также может испортить ваши результаты.

+0

Действительно, при удалении операций, внешних по отношению к этим функциям, но происходящих между каждым вызовом, я видел увеличение в 4 раза. – shodanex