Я уже спрашивал на форумах разработчиков ARM, но ответов нет. https://community.arm.com/developer/tools-software/hpc/f/hpc-user-group/45524/any-neon-instructions-can-be-dual-issued-with-vector-long-multiply-accumulate-smlal-on-cortex-a53-or-a55
Кто-нибудь знает, возможно ли это? Я пробовал несколько комбинаций команд:
A53 A55
smlal.int8 & 64bit load (ld1) 0.97 1.72 instructions/cycle
smlal.int8 & 64bit dup 0.97 0.96
smlal.int8 & 64bit or 0.97 0.96
mla.int8 & 64bit dup 1.79 1.74
mla.int16 & 64bit dup 0.97 0.95
Руководство по оптимизации Cortex A55 содержит противоречивую информацию. https://static.docs.arm.com/epm128372/20/arm_cortex_a55_software_optimization_guide_v2.pdf
В одном месте говорится о двойной проблеме = 01, что в моем понимании означает, что он может выдавать только в слот 0, но позволяет другой инструкции SIMD выдавать в слоте 1.
Во 2-м месте говорится, что двойной выпуск = 00, что означает, что он предотвращает двойной выпуск , Означает ли это, что он использует оба слота?
Что еще удивительнее, даже то, что простое SIMD ИЛИ не может работать параллельно. Что я действительно хочу сделать, так это двойной выпуск dup (указать c lane) с smlal.
Что происходит? Использует ли smlal оба блока SIMD?
Одно предложение заключалось в том, что это может быть узким местом пропускной способности файла регистра
Могут ли Cortex-A57 выполнять 128-битные неоновые инструкции с двумя выпусками?
Это имеет смысл, потому что, в отличие от почти всех других инструкций, smlal берет 3 операнда и записывает вывод шириной в 2 раза, тогда как обычный mla выполняет только 3 чтения и 1 запись. И было бы очень неразумно добавлять третий порт записи в регистровый файл NEON для поддержки записи 128-битного вывода smlal и еще одного 64-битного вывода из 2-й инструкции
Другое объяснение состоит в том, что некоторые инструкции не могут быть выполнены дважды цикл (т. е. «векторная нагрузка не может быть выдана на 4-м цикле каждого кадра»)
https://github.com/Tencent/ncnn/wiki/arm-a53-a55-dual-issue
uint8_t data[32] __attribute__((aligned(32)));
for (int i = 0; i < N; i += 16)
{
asm volatile(
"smlal v9.8h, v0.8b, v0.8b\n"
"ld1 {v0.8b},%0\n"
"smlal v10.8h, v1.8b, v1.8b\n"
"ld1 {v1.8b},%0\n"
"smlal v11.8h, v2.8b, v2.8b\n"
"ld1 {v2.8b},%0\n"
"smlal v12.8h, v3.8b, v3.8b\n"
"ld1 {v3.8b},%0\n"
"smlal v13.8h, v4.8b, v4.8b\n"
"ld1 {v4.8b},%0\n"
"smlal v14.8h, v5.8b, v5.8b\n"
"ld1 {v5.8b},%0\n"
"smlal v15.8h, v6.8b, v6.8b\n"
"ld1 {v6.8b},%0\n"
"smlal v0.8h, v7.8b, v7.8b\n"
"ld1 {v7.8b},%0\n"
"smlal v1.8h, v8.8b, v8.8b\n"
"ld1 {v8.8b},%0\n"
"smlal v2.8h, v9.8b, v9.8b\n"
"ld1 {v9.8b},%0\n"
"smlal v3.8h, v10.8b, v10.8b\n"
"ld1 {v10.8b},%0\n"
"smlal v4.8h, v11.8b, v11.8b\n"
"ld1 {v11.8b},%0\n"
"smlal v5.8h, v12.8b, v12.8b\n"
"ld1 {v12.8b},%0\n"
"smlal v6.8h, v13.8b, v13.8b\n"
"ld1 {v13.8b},%0\n"
"smlal v7.8h, v14.8b, v14.8b\n"
"ld1 {v14.8b},%0\n"
"smlal v8.8h, v15.8b, v15.8b\n"
"ld1 {v15.8b},%0\n"
: :"m"(data));
}