Оптимизация сборки RGBA-›RGB arm64

Я написал эту очень наивную реализацию NEON для преобразования из RGBA в RGB. Это работает, но мне было интересно, есть ли что-нибудь еще, что я мог бы сделать для дальнейшего улучшения производительности.

Я попытался поиграть с размером предварительной выборки и немного развернуть цикл, но производительность не сильно изменилась. Кстати, есть ли какое-нибудь практическое правило, когда дело доходит до измерения предварительной выборки? В сети ничего полезного не нашел. Кроме того, в «Обзоре набора инструкций ARMv8» я вижу также предварительную выборку для хранилища, чем это полезно?

В настоящее время я получаю около 1,7 мс для преобразования изображения 1280x720 на iPhone5s.

// unsigned int * rgba2rgb_neon(unsigned int * pDst, unsigned int * pSrc, unsigned int count);
_rgba2rgb_neon:
    cmp     w2, #0x7
    b.gt    loop

    mov     w0, #0
    ret

loop:
    prfm    pldl1strm, [w1, #64]

    ld4.8b  {v0, v1, v2, v3}, [w1], #32
    ld4.8b  {v4, v5, v6, v7}, [w1], #32

    prfm    pldl1strm, [w1, #64]

    st3.8b  {v0, v1, v2}, [w0], #24
    st3.8b  {v4, v5, v6}, [w0], #24

    subs    w2, w2, #16
    b.gt    loop

done:
    ret

person Tomas Camin    schedule 18.12.2013    source источник


Ответы (2)


Во-первых (поскольку я предполагаю, что вы ориентируетесь на iOS), vImage (часть Accelerate.framework) обеспечивает это преобразование для вас, как vImageConvert_RGBA8888toRGB888. Преимущество этого заключается в том, что он доступен на всех системах iOS и OS X, поэтому вам не нужно писать отдельные реализации для arm64, armv7s, armv7, i386, x86_64.

Теперь, возможно, вы сами пишете это преобразование в качестве упражнения, а не потому, что вы просто не знали, что оно уже доступно. В этом случае:

  • Избегайте использования ld[34] или st[34]. Они удобны, но обычно медленнее, чем использование ld1 и перестановки.
  • Для полностью обычных шаблонов доступа к данным, подобных этому, ручная предварительная выборка не требуется.
  • Загрузите четыре 16-битных вектора RGBA с помощью ld1.16b, извлеките из них три 16-битных вектора RGB с помощью трех инструкций tbl.16b и сохраните их с помощью st1.16b.
  • В качестве альтернативы попробуйте использовать невременную загрузку и сохранение (ldnp/stnp), так как размер вашего изображения слишком велик, чтобы поместиться в кеши.

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

person Stephen Canon    schedule 18.12.2013
comment
Тестирование на iPad Mini Retina (процессор Apple A7), по-видимому, указывает на то, что невременная подсказка для сохранения не влияет на производительность. - person BitBank; 16.01.2015
comment
@BitBank: условия, при которых невременные хранилища повышают производительность, довольно сложно охарактеризовать. Важно иметь в виду, что одно из их самых больших преимуществ заключается в том, что они избегают выделения во внутренний кеш, а это означает, что их влияние иногда видно только в коде, окружающем цикл, который был изменен для их использования. Мое руководство таково: попробуйте их, измерьте производительность всей программы и, если они дадут улучшение, используйте их. - person Stephen Canon; 16.01.2015
comment
Я пришел к такому выводу, протестировав функцию, которая записывает в буфер изображения больше, чем кеш L2. Данные только записываются и не используются снова до тех пор, пока позже. Это казалось идеальным случаем, чтобы попробовать потоковую версию инструкции сохранения. Мне нужно проверить это на Nvidia K1 Denver, чтобы увидеть, отличается ли поведение от Apple A7. Скоро обновление... - person BitBank; 16.01.2015

См. также vImageFlatten_RGBA8888toRGB888, если вы хотите сделать что-то интересное с альфа-каналом, кроме того, чтобы бросить его через плечо.

person Ian Ollmann    schedule 13.01.2014