Как сказано в комментариях, ARM-Neon имеет инструкцию, которая напрямую выполняет то, что вы хотите, то есть вычисляет абсолютную разницу беззнаковых байтов и накапливает ее в беззнаковые короткие целые числа.
Предполагая SAD_WIDTH+1==8
Вот очень простая реализация с использованием встроенных функций (на основе упрощенной версии @nemequ):
void sadCol(uint8_t* leftRank,
uint8_t* rightRank,
int j,
int d ,
uint16_t* cost) {
const int SAD_WIDTH = 7;
const int imgWidth = 320;
const int SAD_WIDTH_STEP = SAD_WIDTH * imgWidth;
uint16x8_t cost_8 = {0};
for(int m = 0; m < SAD_WIDTH_STEP; m = m + imgWidth ) {
cost_8 = vabal_u8(cost_8, vld1_u8(&leftRank[j+m]), vld1_u8(&rightRank[j+m-d]));
};
vst1q_u16(cost, cost_8);
};
vld1_u8
загружает 8 последовательных байтов, vabal_u8
вычисляет абсолютную разницу и накапливает ее до первогорегистр.Наконец, vst1q_u16
сохраняет регистр в памяти.
Вы можете легко настроить imgWidth
и SAD_WIDTH_STEP
функциональные параметры.Если SAD_WIDTH+1
отличается от кратного 8, вы можете написать для этого еще один цикл.
У меня нет под рукой платформы ARM для его проверки, но "она компилируется": https://godbolt.org/z/vPqiYI (исборка выглядит нормально, на мой взгляд).Если вы оптимизируете с помощью -O3
, gcc развернет цикл.