четверг, 4 декабря 2008 г.

Несколько кусков кода

Хочу предложить некую подборку маленьких кусочков кода, для стандартных задач, часто встречающихся при программировании на MMX-SSE. Тут никаких откровений не будет, но может кому пригодится.

1. занулить все биты в SSE регистре (xmm0)

pxor  xmm0, xmm0


2. выставить все биты в SSE регистре (xmm0)

pcmpeqb  xmm0, xmm0


3. дублируем word CX в xmm0


movd xmm0, ecx ; xmm0 = ** ** ** ** | ** ** ** ** | ** ** ** ** | 00 00 VV UU
punpcklwd xmm0, xmm0 ; xmm0 = ** ** ** ** | ** ** ** ** | 00 00 00 00 | VV UU VV UU
pshufd xmm0, xmm0, 0 ; xmm0 = VV UU VV UU | VV UU VV UU | VV UU VV UU | VV UU VV UU


4. дублируем байт CL в xmm0



movd xmm0, ecx ; xmm0 = ** ** ** ** | ** ** ** ** | ** ** ** ** | 00 00 00 UU
punpcklwd xmm0, xmm0 ; xmm0 = ** ** ** ** | ** ** ** ** | 00 00 00 00 | 00 UU 00 UU
pshufd xmm0, xmm0, 0 ; xmm0 = 00 UU 00 UU | 00 UU 00 UU | 00 UU 00 UU | 00 UU 00 UU
movdqa xmm1, xmm0 ; xmm1 = 00 UU 00 UU | 00 UU 00 UU | 00 UU 00 UU | 00 UU 00 UU
psllw xmm1, 8 ; xmm1 = UU 00 UU 00 | UU 00 UU 00 | UU 00 UU 00 | UU 00 UU 00
por xmm0, xmm1 ; xmm0 = UU UU UU UU | UU UU UU UU | UU UU UU UU | UU UU UU UU


5. Перевернуть SSE регистр побайтово


__declspec( align(16) ) static BYTE g_carShufleMask[16] =
{
0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
};
_asm
{
movdqa xmm1, oword ptr [g_carShufleMask]
pshufb xmm0, xmm1
}


Последнее надо использовать аккуратно, pshufb - SSE2 команда (например, MSVC2003 вообще про нее не знает).

На последок. Крайне рекомендую найти и почитать статью "Using Block Prefetch for Optimized Memory Performance" очень хороший пошаговый разбор оптимизации функции memcpy с использованием кеша процессора. Скорость увеличивается в 2.5 раза (по статье в 3, но у меня на четырех компьютерах было от 2 до 2.5). Понятно, что ускорение memcpy (в особенности в тех условиях, которые заявлены в статье) не слишком интересно - но в целом почитать для начинающих вроде меня полезно.

Комментариев нет: