Neon на Android ограничен доступом к памяти?

Я запрограммировал подпрограмму для обработки одиночных массивов с плавающей запятой с использованием Neon на платформе Android, в частности Samsung S4, и обнаружил, что мои подпрограммы Neon ограничены доступом к данным массива. Ради интереса, фрагмент ниже:

Неон

m1 =  vmulq_f32(*(float32x4_t *)&ey[i][j],*(float32x4_t *)&caey[i][j]);
                m2 =  vsubq_f32(*(float32x4_t *)&hz[i-1][j],*(float32x4_t *)&hz[i][j]);
                m3 =  vmulq_f32(*(float32x4_t *)&cbey[i][j],m2);
                m4 =  vaddq_f32(m1,m3); 
                vst1q_f32(&ey[i*je+j],m4);

Серийный

ey[i][j] = caey[i][j] * ey[i][j] + cbey[i][j] * ( hz[i-1][j] - hz[i][j] ); 

Построен на телефоне Android с использованием C4droid gcc, а также AIDE-JNI. Приведенный выше встроенный код Neon требует немного больше времени для обработки, чем последовательный эквивалент. При замене данных массива фиктивными константами с плавающей запятой код работает почти в 4 раза быстрее, чем последовательный код с данными массива, хотя, конечно, это приведет к бессмысленным результатам (это подтверждает, что проблема производительности связана с доступом к данным). Мой эквивалентный код SSE и AVX на других платформах обеспечивает хорошее ускорение.

Я пробовал эквивалентные массивы 1D и предварительную выборку данных с помощью __builtin_prefetch , но не могу ускорить доступ к данным для встроенных функций Neon.

Есть ли что-нибудь еще, что я могу попробовать улучшить производительность доступа к данным на телефоне Android?


person magicfoot    schedule 15.12.2014    source источник
comment
Ручная предварительная выборка — это что-то вроде черной магии, поэтому, не зная точно, как выглядит цикл и структура данных (т. е. сколько итераций, порядок i и j, выравнивание строки кэша и т. д.), немного сложно сказать. Разборку цикла NEON тоже стоит посмотреть, просто чтобы убедиться, что компилятор не делает ничего особенно глупого. Однако, поскольку вы фактически ничего не делаете, кроме доступа к памяти (сами вычисления довольно тривиальны), возможно, вы уже насыщаете полосу пропускания L2 благодаря автоматической предварительной выборке, и в этом случае вам некуда деваться.   -  person Notlikethat    schedule 15.12.2014
comment
1) GCC известен созданием плохого кода из встроенных функций. 2) Вы оставляете регистр/память для чтения/записи в руках компилятора и не используете чередование для уменьшения простоев. 3) Мы не знаем вашу ситуацию с выравниванием памяти. 4) Правильная предварительная выборка, вероятно, немного ускорит ее.   -  person BitBank    schedule 15.12.2014
comment
Встроенные функции Neon были обновлены в gcc4.9. Инструкция pld заполнит строки кэша. Ваш размер/геометрия линии L1/L2 и скорость DDR будут иметь значение. Вам нужно выполнить предварительную выборку каждого из пяти элементов, и кажется, что предыдущий массив hz уже может быть в вашем кеше. Вы также можете попробовать -ffast-math, так как я думаю, что плавающая точка ARM не на 100% совместима с IEEE, и компилятор часто будет вставлять некоторые педантичные проверки; но действительно нужно смотреть на ассемблере. Связано: Неоновый поплавок.   -  person artless noise    schedule 15.12.2014
comment
Кроме того, это устройство поставляется с различными конфигурациями ЦП; SnapDragon 600 SOC или четырехъядерная система A15/A7. Вероятно, от этого зависят результаты. Строка A15 L1 состоит из 16 слов, а A7 — всего из 8. >Вот патч gcc, в котором упоминаются проблемы de-norm NEON. Очевидно, что если вам нужна эта точность (близкая к нулю), то вы не можете использовать -ffast-math.   -  person artless noise    schedule 15.12.2014
comment
Я чувствую здесь неладное: GCC, похоже, снова виноват. Я мог бы дать вам окончательный ответ, если бы вы разместили разборку. Две вещи, которые я могу сказать вам сейчас, это то, что вы должны развернуться, чтобы задержки инструкций исчезли/уменьшились, и заменить mul + add на mla.   -  person Jake 'Alquimista' LEE    schedule 16.12.2014