В некоторых случаях для этого есть библиотеки. И, в частности, есть приемы, которые вы можете играть с векторизованными данными (например, четыре 32-битных элемента в 128-битном векторе, но это также относится к четырем 8-битным байтам в 32-битном регистре), чтобы работать быстрее, чем отдельные доступ к элементам.
Для транспонирования стандартная идея состоит в том, что вы используете «перемешивающие» инструкции, которые позволяют вам создавать новый вектор данных из двух существующих векторов в любом порядке. Вы работаете с 4x4 блоками входного массива. Итак, начиная, у вас есть:
v0 = 1 2 3 4
v1 = 5 6 7 8
v2 = 9 A B C
v3 = D E F 0
Затем вы применяете команды тасования к первым двум векторам (чередование их нечетных элементов, A0B0 C0D0 -> ABCD и чередование их четных элементов, 0A0B 0C0D -> ABCD) и к последним двум, чтобы создать новый набор векторов с каждым транспонированным блоком 2x2:
1 5 3 7
2 6 4 8
9 D B F
A E C 0
Наконец, вы применяете инструкции перемешивания к нечетной паре и четной паре (объединяя их первые пары элементов, AB00 CD00 -> ABCD и их последние пары, 00AB 00CD -> ABCD), чтобы получить:
1 5 9 D
2 6 A E
3 7 B F
4 8 C 0
И там 16 элементов, транспонированных в восьми инструкциях!
Теперь, для 8-битных байтов в 32-битных регистрах, ARM не имеет точно инструкций тасования, но вы можете синтезировать то, что вам нужно, с помощью Shift и инструкции SEL (выборки), а второй набор тасовок вы можете выполнять в одной инструкции с инструкциями PKHBT (упаковать верхнюю часть наполовину) и PKHTB (упаковать верхнюю часть наполовину).
Наконец, если вы используете большой ARM-процессор с NEON-векторизацией, вы можете сделать что-то подобное с 16-элементными векторами в 16x16 блоках.