ARM NEON: как реализовать поисковую таблицу размером 256 байт

Я портирую написанный мной код на NEON, используя встроенную сборку.

Мне нужно преобразовать байтовые значения в диапазоне [0..128] в другие байтовые значения в таблице, которые принимают полный диапазон [0..255]

Таблица короткая, но математика, стоящая за ней, непроста, поэтому я думаю, что не стоит рассчитывать ее каждый раз «на лету». Итак, я хочу попробовать таблицы поиска.

Я использовал VTBL для 32-байтового случая и работает, как ожидалось

Для всего диапазона одна из идей - сначала сравнить диапазон, в котором находится источник, и выполнить разные поиски (т. Е. Иметь 4 32-битные таблицы поиска).

У меня вопрос: Есть ли более эффективный способ сделать это?

ИЗМЕНИТЬ

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

// Have the original data in d0
// d1 holds #32 value 
// d6,d7,d8,d9 has the images for the values [0..31] 

    //First we look for the 0..31 images. The values out of range will be 0
    "vtbl.u8 d2,{d6,d7,d8,d9},d0    \n\t"

    // Now we sub #32 to d1 and find the images for [32...63], which have been previously loaded in d10,d11,d12,d13
    "vsub.u8 d0,d0,d1\n\t"              
    "vtbl.u8 d3,{d10,d11,d12,d13},d1    \n\t"

    // Do the same and calculating images for [64..95]
    "vsub.u8 d0,d0,d1\n\t"
    "vtbl.u8 d4,{d14,d15,d16,d17},d0    \n\t"

    // Last step: images for [96..127]
    "vsub.u8 d0,d0,d1\n\t"
    "vtbl.u8 d5,{d18,d19,d20,d21},d0    \n\t"

    // Now we add all. No need to saturate, since only one will be different than zero each time
    "vadd.u8 d2,d2,d3\n\t"
    "vadd.u8 d4,d4,d5\n\t"
    "vadd.u8 d2,d2,d4\n\t"   // Leave the result in d2

person Jordi C.    schedule 03.03.2014    source источник
comment
Я думаю, вы на правильном пути - 4 x VTBL, вероятно, лучший вариант, если вам нужен параллельный поиск.   -  person Paul R    schedule 04.03.2014
comment
Спасибо. Это выглядит хорошо до планирования и оптимизации. Только что отредактировал пост с примером   -  person Jordi C.    schedule 04.03.2014
comment
Если функция монотонная, вы можете опустить vadds и повторно использовать vtbx d0, { dXXXX }, d0; vsub d0, d0, d1;. Таблицы должны быть скорректированы, чтобы учесть смещение n * d1, убедившись, что уже обработанные значения никогда не могут быть вычтены до диапазона 0..31.   -  person Aki Suihkonen    schedule 05.03.2014
comment
Никогда не думал об этом! В этом случае он не монотонный, но может быть использован в определенных случаях.   -  person Jordi C.    schedule 05.03.2014


Ответы (1)


Правильная последовательность - через

vtbl d0, { d2,d3,d4,d5 }, d1   // first value
vsub d1, d1, d31               // decrement index
vtbx d0, { d6,d7,d8,d9 }, d1   // all the subsequent values
vsub d1, d1, d31               // decrement index
vtbx d0, { q5,q6 }, d1         // q5 = d10,d11
vsub d1, d1, d31
vtbx d0, { q7,q8 }, d1

Разница между vtbl и vtbx заключается в том, что vtbl обнуляет элемент d0, когда d1 ›= 32, тогда как vtbx оставляет исходное значение в d0 нетронутым. Таким образом, нет необходимости в уловках, как в моем комментарии, и нет необходимости объединять частичные значения.

person Aki Suihkonen    schedule 03.01.2021