2012-12-04 3 views
4

Я работаю над оптимизацией ARM, используя встроенные средства NEON, из кода C++. Я понимаю и обрабатываю большинство проблем с печатанием, но я застрял на этом:Совместимость типов данных с NEON intrinsics

Инструкция vzip_u8 возвращает значение uint8x8x2_t (фактически массив из двух uint8x8_t). Я хочу присвоить возвращаемое значение равному uint16x8_t. Я не вижу подходящего для этого vreinterpretq, и простые отбрасывания отклоняются.

+0

Просто обнаружил в руководстве, uint8x8x2_t называется «Вектор массив типа данных». Но до сих пор не знаю, как конвертировать. –

+0

Можете ли вы опубликовать небольшой фрагмент, чтобы продемонстрировать свой вопрос? – auselen

ответ

1

Я нашел обходное решение: учитывая, что элемент val является массивом, поэтому он рассматривается как указатель. Выполняется литье и отсрочка указателя! [Принимая во внимание, принимая адрес данных поднимает «адрес временного» предупреждения.]

uint16x8_t Value= *(uint16x8_t*)vzip_u8(arg0, arg1).val; 

Оказывается, что это компилирует и выполняет, как следует (по крайней мере, в случае, если я пробовал). Я не смотрел на код сборки, поэтому я не могу предоставить его правильно реализовано (я имею в виду просто сохранить значение в регистре вместо записи/чтения в/из памяти.)

+1

Любой, кто сказал мне, почему они сделали это настолько ограниченным, приветствуется ... –

+0

Пожалуйста, взгляните на [мой ответ] (http://stackoverflow.com/a/29229662/2436175) – Antonio

+0

Я не эксперт, но я думаю, что будет [нарушать правила строгого сглаживания] (http://stackoverflow.com/a/29253236/2436175). Плюс риск [упомянутый auselan] (http://stackoverflow.com/a/13734838/2436175), что 2 вектора векторов не связаны в одном и том же 128-битном регистре. – Antonio

5

Некоторые определения, чтобы четко ответить ...

NEON имеет 32 регистра, шириной 64 бит (двойной вид в виде 16 регистров, ширина 128 бит).

Блок NEON может просматривать тот же регистр банк как:

  • шестнадцать 128-битный квадраслово регистров, Q0-Q15
  • тридцать два 64-разрядных двойных регистры, D0-D31 ,

uint16x8_t представляет собой тип, который требует 128-битного хранения, таким образом, она должна быть в quadword регистре.

ARM NEON Intrinsics имеет определение под названием vector array data type в ARM® C Language Extensions:

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

vzip инструкция

... чередует элементы двух векторов.

vzip Dd, Dm

и имеет intrinsic как

uint8x8x2_t vzip_u8 (uint8x8_t, uint8x8_t) 

из них мы можем заключить, что uint8x8x2_t на самом деле список из двух случайных пронумерованных регистров двойных, потому что инструкции vzip Безразлично у нас нет требования по порядку входных регистров.

Теперь ответ ...

uint8x8x2_t может содержать непоследовательные два dualword регистров, а uint16x8_t это структура данных, состоящую из двух последовательных регистров dualword, который первые из них имеет даже индекс (D0-D31 -> Q0 -Q15).

Из-за этого вы не можете отличить vector array data type с двумя регистрами двойного слова в регистр квадрациклов ... легко.

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

+0

Теперь все ясно, спасибо. uint8x8x2_t должен быть «псевдотипом», поскольку он описывает возможные несмежные данные. Но мой первоначальный вопрос остается: «вы можете просто заставить преобразовать». Как ??? –

+0

Но, как я уже сказал, компилятор может исправить это для вас. Проблема в производительности может пострадать. Вы должны проверить двоичный файл. – auselen

+0

Моя проблема заключалась в том, что я не мог найти способ заставить компилятор принять приведение. –

-1

Его ошибка в GCC (теперь исправлена) на 4.5 и 4.6 серии.

Bugzilla ссылка http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48252

Пожалуйста, исправление от этой ошибки и применить к GCC источника и восстановить его.

+0

Привет. Спасибо, что внесли свой вклад в эту должность. Он не затрагивает текущую проблему, которая является вопросом синтаксической/семантической несовместимости, а не ошибкой генерации кода в компиляторе. –

4

Вы можете построить 128-битный вектор из двух 64-битных векторов, используя vcombine_ * intrinsics. Таким образом, вы можете достичь того, чего хотите.

#include <arm_neon.h> 

uint8x16_t f(uint8x8_t a, uint8x8_t b) 
{ 
    uint8x8x2_t tmp = vzip_u8(a,b); 
    uint8x16_t result; 
    result = vcombine_u8(tmp.val[0], tmp.val[1]); 
    return result; 
} 
+0

Интересно, спасибо. Я рассмотрю его (но, скорее всего, не скоро, это спящий проект). –

0

У меня возникла такая же проблема, поэтому я представил a flexible data type.

теперь я могу, следовательно, определить следующее:

typedef NeonVectorType<uint8x16_t> uint_128bit_t; //suitable for uint8x16_t, uint8x8x2_t, uint32x4_t, etc. 
typedef NeonVectorType<uint8x8_t> uint_64bit_t; //suitable for uint8x8_t, uint32x2_t, etc.