Загрузить 8bit uint8_t как uint32_t? - PullRequest
5 голосов
/ 09 сентября 2010

мой проект обработки изображений работает с изображениями в градациях серого.У меня ARM Cortex-A8 процессорная платформа.Я хочу использовать NEON.

У меня есть изображение в градациях серого (рассмотрите пример ниже), и в моем алгоритме я должен добавить только столбцы.

Как я могу загрузить четыре 8-битных значения пикселей параллельно, которые равны uint8_t , как четыре uint32_t в один из 128-битных регистров NEON?Что мне нужно использовать для этого?

Я имею в виду:

alt text

Я должен загрузить их как 32-битные, потому что, если вы посмотрите внимательно, моментЯ делаю 255 + 255 - это 512, которые нельзя хранить в 8-битном регистре.

например,

255 255 255 255 ......... (640 pixels)
255 255 255 255
255 255 255 255
255 255 255 255
.
.
.
.
.
(480 pixels) 

Ответы [ 5 ]

11 голосов
/ 10 сентября 2010

Я рекомендую вам потратить немного времени на понимание того, как SIMD работает на ARM.Посмотрите на:

Посмотрите на:

  1. http://blogs.arm.com/software-enablement/161-coding-for-neon-part-1-load-and-stores/
  2. http://blogs.arm.com/software-enablement/196-coding-for-neon-part-2-dealing-with-leftovers/
  3. http://blogs.arm.com/software-enablement/241-coding-for-neon-part-3-matrix-multiplication/
  4. http://blogs.arm.com/software-enablement/277-coding-for-neon-part-4-shifting-left-and-right/

, чтобы начать работу.Затем вы можете реализовать свой код SIMD, используя встроенный ассемблер или соответствующие встроенные функции ARM, рекомендованные domen.

5 голосов
/ 09 сентября 2010

Зависит от вашего компилятора и (возможно, отсутствия) расширений.

Т.е.. для GCC это может быть отправной точкой: http://gcc.gnu.org/onlinedocs/gcc/ARM-NEON-Intrinsics.html

3 голосов
/ 26 октября 2010

Если вам необходимо суммировать до 480 8-битных значений, технически вам потребуется 17 бит промежуточного хранилища. Однако, если вы выполняете сложение в два этапа, то есть с верхними 240 строками и нижними 240 строками, вы можете делать это по 16 бит. Затем вы можете добавить результаты из двух половинок, чтобы получить окончательный ответ.

На самом деле есть инструкция NEON, которая подходит для вашего алгоритма, и называется vaddw. Он добавит вектор dword к вектору qword, причем последний содержит элементы, которые в два раза шире, чем первый. В вашем случае vaddw.u8 можно использовать для добавления 8 пикселей к 8 16-разрядным аккумуляторам. Затем vaddw.u16 можно использовать для добавления двух наборов из 8 16-разрядных аккумуляторов в один набор из 8 32-разрядных. Обратите внимание, что для получения обеих половин необходимо использовать инструкцию дважды.

При необходимости вы также можете преобразовать значения обратно в 16-битные или 8-битные, используя vmovn или vqmovn.

2 голосов
/ 09 апреля 2011

Нет инструкции, которая может загрузить ваше 4-битное значение в 4-битный регистр.

Вы должны загрузить их, а затем дважды использовать vshl. поскольку неон не может использовать 32 регистра, вам придется работать с 8 пикселями (а не с 4)

Вы можете использовать только 16-битный регистр. этого должно быть достаточно ...

0 голосов
/ 07 августа 2012

Загрузите 4 байта, используя инструкцию загрузки с одной дорожкой (vld1 <register>[<lane>], [<address]), в q-регистр, а затем используйте две инструкции длины хода (vmovl), чтобы повысить их сначала до 16, а затем до 32 бит.Результатом должно быть что-то вроде (в синтаксисе GNU)

vld1 d0[0], [<address>] @Now d0 = (*<addr>, *<addr+1>, *<addr+2>, *<addr+3>, <junk>, ... <junk> )
vmovl.u8 q0, d0 @Now q1 = (d0, d1) = ((uint16_t)*<addr>, ... (uint16_t)*<addr+3>, <junk>, ... <junk>)
vmovl.u16 q0, d2 @Now d0 = ((uint32_t)*<addr>, ... (uint32_t)*<addr+3>), d1 = (<junk>, ... <junk>)

Если вы можете гарантировать, что <address> выровнено по 4 байта, вместо этого напишите [<address>: 32] в инструкции загрузки, чтобы сохранить цикл илидва.Если вы сделаете это, а адрес не выровнен, вы получите ошибку, однако.

Хм, я просто понял, что вы хотите использовать встроенные функции, а не ассемблер, так что здесь то же самое с встроенными функциями.

uint32x4_t v8; // Will actually hold 4 uint8_t
v8 = vld1_lane_u32(ptr, v8, 0);
const uint16x4_t v16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(v8)));
const uint32x4_t v32 = vmovl_u16(v16);
...