В чем разница между loadu / lddqu и оператором присваивания? - PullRequest
0 голосов
/ 29 апреля 2020

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

__m128i vector2 = vector1;
__m128i vector2 = _mm_loadu_si128(&vector1);

Итак, в чем отличие двух приведенных выше утверждений?

1 Ответ

0 голосов
/ 29 апреля 2020

Как сказал Питер Кордес в своем комментарии, если vector1 действительно является __m128i, то это просто излишне сложно.

Однако это не тот случай использования _mm_loadu_si128. Хотя тип аргумента __m128i const*, это больше касается отсутствия хороших опций и плохих решений.

_mm_loadu_si128 действительно предназначен для загрузки любых 16 байтов данных в векторный регистр. Если вы хотите загрузить данные, которые уже выровнены по 16-байтовым границам, вы должны использовать _mm_load_si128. Если ваши данные не выровнены по 16-байтовым границам, это не на самом деле a __m128i, поэтому тип параметра в лучшем случае вводит в заблуждение.

Причина, по которой Intel (или кто-либо еще) выбрал использовать __m128i const* не совсем понятно, но, если честно, хороших вариантов не так много. int const* на самом деле не имеет смысла, потому что то, что мы пытаемся загрузить, не всегда 32-битные целые числа со знаком. Они могли бы сделать _mm_loadu_epi8, _mm_loadu_epi16, _mm_loadu_epi32 и т. Д. c., Но даже это было бы не совсем правильно, потому что данные не нужно выравнивать по _Alignof(int), _Alignof(short) , et c. , хотя char здесь действительно хорошо работают.

Возможно, правильным выбором будет аргумент void*, но я думаю, что Intel хотела сигнализировать, что они действительно хотели 16 байтов данных. char mem_addr[16] было бы хорошо в C99 +, но не в C ++, и хотя SSE2 вышел примерно в то же время, что и C99, многие компиляторы не поддерживали C99 (MSV C все еще не поддерживает!).

В основном, для этой функции игнорируйте типы параметров и прочитайте описание.

...