Переупорядочить значения при сохранении из регистров NEON

У меня есть 128 32-битных значений (пронумерованных от 0 до 127), и они упорядочены следующим образом:

0, 32, 64, 96, 1, 33, 65, 97, ... 31, 63, 95, 127

При таком порядке я загружаю их группами по 4 в регистры NEON для выполнения некоторых вычислений (которые требуют такого порядка). Таким образом, у меня есть q0 = (0, 32, 64, 96) ... и так далее.

Мне было интересно, есть ли какой-нибудь простой способ сохранить их обратно в память в их естественном порядке (0 1 2 3...)

Другими словами, есть ли более простой способ или трюк для этого:

vst1.u32 {d0[0]}, [r0]
vst1.u32 {d0[1]}, [r0,#128]
vst1.u32 {d1[0]}, [r0,#256]
vst1.u32 {d1[1]}, [r0,#384]
vst1.u32 {d2[0]}, [r0,#4]
vst1.u32 {d2[1]}, [r0,#132]
...

Я не совсем понимаю использование суффикса @alignment с инструкциями vstx и vldx. Разве это не тот случай, когда это может быть полезно?


person NumberFour    schedule 27.04.2013    source источник
comment
Извините, если мой вопрос глупый, но ваш порядок начинается с 1, 32, 64, 96; (+31,+32,+32), разве оно не должно заканчиваться на 31,62,94,126, 32,63,95,127, 33,64,96,128?   -  person Étienne    schedule 27.04.2013
comment
Спасибо! Конечно, это была опечатка.   -  person NumberFour    schedule 27.04.2013


Ответы (1)


Выравнивание (@128, @256) используется, чтобы намекнуть процессору, что чтение/запись не пересекает строку кэша. В этих случаях количество выполняемых микроопераций (и, в конечном счете, используемых циклов) может быть уменьшено.

Вместо этого ваше приложение выиграет от формата инструкций, который позволяет сохранять/загружать столбцы. Руководство Arm называет эти полосы, как в подразделе (Сохранить в памяти одну полосу структуры из N элементов).

Формат поддерживает как последовательные регистры: {d0,d1,d2,...}, так и пропуск одного регистра {d0,d2,d4,...}.

 mov #128, r1  // initialize value for increment
 vst4.32 { d0[0], d2[0], d4[0], d6[0] }, [r0], r1   // columns 0..1
 vst4.32 { d0[1], d2[1], d4[1], d6[1] }, [r0], r1   // store at offset 128
 vst4.32 { d1[0], d3[0], d5[0], d7[0] }, [r0], r1   // columns 2..3
 vst4.32 { d1[1], d3[1], d5[1], d7[1] }, [r0], r1   // columns 2..3
 ... etc ...

Это, пожалуй, лучшее, что можно сделать, так как регистров не хватает, чтобы все расставить по местам. Я считаю, что потребуется 32 Q-регистра.

person Aki Suihkonen    schedule 28.04.2013
comment
Это приятно. Но не могли бы вы объяснить, что такое dx[2] и dx[3]? Я думал, что dx имеет ширину 64 бита, поэтому он имеет только dx[0] и dx[1] (младшие 32-битные и старшие 32-битные половины соответственно) - person NumberFour; 28.04.2013
comment
Вы также забыли уменьшить r0, так как суффиксные приращения являются постоянными. В любом случае, я изменил свой код, и он работает довольно хорошо, поэтому я принимаю ваш ответ. Спасибо! - person NumberFour; 28.04.2013
comment
Вы правы, 32-битных индексов d_even[2..3] не существует. На самом деле это будет d_odd[0..1]. Во всяком случае, я просто хотел предоставить некоторый концептуальный код. - person Aki Suihkonen; 28.04.2013