Увеличить размер типа данных в регистре SSE

Я использую VS2005 (на работе) и мне нужен встроенный SSE, который делает следующее:

У меня есть уже существующий __m128i n, заполненный 16-битными целыми числами a_1,a_2,....,a_8.

Поскольку для некоторых вычислений, которые я сейчас хочу выполнить, требуется 32 бита вместо 16, я хочу извлечь два набора из четырех 16-битных целых чисел из n и поместить их в два разделенных __m128i, которые содержат a_1,...,a_4 и a_5,...,a_8 соответственно.

Я мог бы сделать это вручную, используя различные встроенные функции _mm_set, но это привело бы к восьми mov в сборке, и я надеялся, что будет более быстрый способ сделать это.


person TravisG    schedule 06.02.2013    source источник
comment
Взгляните на эти встроенные функции SSE4.1. Вы можете получить то, что хотите, используя два из них и распаковку/перетасовку.   -  person Mysticial    schedule 06.02.2013
comment
Я не думаю, что они доступны в VS2005.   -  person TravisG    schedule 06.02.2013
comment
Эх... VS2005. Скажи своему боссу, чтобы сжег его... огнем. :)   -  person Mysticial    schedule 06.02.2013
comment
В противном случае... Вы застрянете на долгом пути с неприятным беспорядком перетасовок, смен и масок.   -  person Mysticial    schedule 06.02.2013
comment
@Mystical Это не только мой босс. У нас уже давно есть лицензии на все новые Visual Studio (они также используются в некоторых небольших проектах), но по разным причинам мы не можем постоянно все менять. У многих людей много зависимостей от VS2005 (не только у нас, но и у внешних клиентов, которые используют наши API, поэтому мы не могли, например, переключиться на VS2012 и использовать материал C++11). Кроме того, VS2005 не так уж и плох. Я хотел бы использовать больше С++ 11, и когда дело доходит до таких технических моментов, раздражает отсутствие функций (или профилировщика из VS12), но в остальном все в порядке.   -  person TravisG    schedule 06.02.2013
comment
Связано: stackoverflow.com/q/12121640/743214.   -  person Christian Rau    schedule 06.02.2013


Ответы (1)


Предполагая, что я правильно понимаю, чего вы хотите достичь (распаковать 8 x 16 бит в одном векторе в два вектора 4 x 32 битных целых числа), я обычно делаю это так в SSE2 и более поздних версиях:

__mm128i v = _mm_set_epi16(7, 6, 5, 4, 3, 2, 1, 0);  // v = { 7, 6, 5, 4, 3, 2, 1, 0 }
__mm128i v_lo = _mm_srai_epi32(_mm_unpacklo_epi16(v, v), 16); // v_lo = { 3, 2, 1, 0 }
__mm128i v_hi = _mm_srai_epi32(_mm_unpackhi_epi16(v, v), 16); // v_hi = { 7, 6, 5, 4 }
person Paul R    schedule 06.02.2013
comment
Мило... Это не так противно, как я себе представлял. Конечно, я никогда особо не старался, так как обычно у меня есть доступ к SSE4.1. - person Mysticial; 06.02.2013
comment
Но будет ли это быстрее, чем v_lo= _mm_set_epi32(a_1,...,a_4) v_hi = _mm_set_epi32(a_5,a_6,a_7,a_8)? Я могу получить доступ к отдельным значениям через встроенную функцию __m128i, которая кажется объединением, где я могу получить доступ к различным содержащимся типам данных, таким как массив. - person TravisG; 06.02.2013
comment
@TravisG Все будет быстрее, чем использовать _mm_set и извлекать отдельные компоненты. Что ваш код будет делать, так это брать эти значения из регистра SSE в некоторое выровненное хранилище памяти, выполнять некоторые операции, не относящиеся к SSE, для каждого из них, а затем загружать это в другой регистр. Это будет на несколько лиг медленнее, чем выполнять все это вне регистров SSE с кучей операций SEE. В общем, доступ к отдельным компонентам из регистров SSE является убийцей производительности для любого кода SSE, независимо от того, позволяет ли ваша библиотека легко программировать это, предоставляя объединение... - person Christian Rau; 06.02.2013
comment
@TravisG ... Дело не в том, что вы только теряете SIMD-параллелизм. Весь этот доступ к одному компоненту должен поддерживаться кучей операций с памятью, так как SSE не предназначен для этого. - person Christian Rau; 06.02.2013
comment
@TravisG: в дополнение к действительным комментариям Кристиана я просто скажу, что приведенный выше код, хотя он может и выглядит противно, переводится всего в 4 инструкции. Если вы начнете возиться с отдельными элементами вектора, используя скалярный код, вы увидите более 4 инструкций (плюс все другие вышеупомянутые проблемы). - person Paul R; 06.02.2013
comment
Это интересно. Спасибо! - person TravisG; 06.02.2013