Инициализация памяти
| Имя функции | Операция | Инструкция |
| _mm_load_ss | загрузить младшее значение и очистить остальные три значения | MOVSS |
| _mm_load1_ps | загрузить одно значение во все четыре позиции | MOVSS + Shuffling |
| _mm_load_ps | Загрузить четыре значения по выровненному адресу | MOVAPS |
| _mm_loadu_ps | Загрузить четыре значения по невыровненному адресу | MOVUPS |
| _mm_loadr_ps | Загрузить четыре значения в обратном порядке | MOVAPS + Shuffling |
Инициализация значений
| Имя функции | Операция | Инструкция |
| _mm_set_ss | устанавливает самое младшее значение и обнуляет три остальных | составная |
| _mm_set1_ps | устанавливает четыре позиции в одно значение | составная |
| _mm_set_ps | устанавливает четыре значения, выровненные по адресу | составная |
| _mm_setr_ps | устанавливает четыре значения в обратном порядке | составная |
| _mm_setzero_ps | Обнуляет все четыре значения | составная |
Операции записи
| Имя функции | Операция | Инструкция |
| _mm_store_ss | записать младшее значение | MOVSS |
| _mm_store1_ps | записать младшее значение во все четыре позиции | MOVSS + Shuffling |
| _mm_store_ps | записать четыре значения по выровненному адресу | MOVAPS |
| _mm_storeu_ps | записать четыре значения по невыровненному адресу | MOVUPS |
| _mm_storer_ps | записать четыре значения в обратном порядке | MOVAPS + Shuffling |
| _mm_move_ss | записать младшее значение и оставить без изменения три остальных значения | MOVSS |
Поддержка кэш-памяти в SSE
| Имя функции | Операция | Инструкция |
| _mm_prefetch | Загружает одну кэш-строку по указанному адресу в кэш-память | PREFETCH |
| _mm_stream_pi | Записывает данные в память без записи в кэш | MOVNTQ |
| _mm_stream_ps | Записывает данные в память без записи в кэш по адресу, выровненному по 16 байт | MOVNTPS |
| _mm_sfence | Гарантирует, что все предшествующие записи в память завершатся до следующей записи. | SFENCE |
Использование встроенных функций SSE в программе на языке Си
// скалярное произведение векторов
#include <stdio.h>
#include <xmmintrin.h>
#define N 10000000
// «обычная» функция
float inner1(float *x,float *y,int n)
{
float s;
int i;
s=0;
for(i=0;i<n;i++)
s+=x[i]*y[i];
return s;
}
// функция с использованием SSE intrinsics
float inner2(float *x,float *y,int n)
{
float sum;
int i;
__m128 *xx,*yy;
__m128 p,s;
xx=(__m128 *)x;
yy=(__m128 *)y;
s=_mm_set_ps1(0);
for (i=0;i<n/4;i++)
{
p=_mm_mul_ps(xx[i], yy[i]); // векторное умножение четырех чисел
s=_mm_add_ps(s,p); // векторное сложение четырех чисел
}
p=_mm_movehl_ps(p,s); // перемещение двух старших значений s в младшие p
s=_mm_add_ps(s,p); // векторное сложение
p=_mm_shuffle_ps(s,s,1);//перемещение второго значения в s в младшую позицию в p
s=_mm_add_ss(s,p); // скалярное сложение
_mm_store_ss(&sum,s); // запись младшего значения в память
return sum;
}
int main()
{
float *x,*y, s;
long t;
int i;
// выделение памяти с выравниванием
x=(float *)_mm_malloc(N*sizeof(float),16);
y=(float *)_mm_malloc(N*sizeof(float),16);
for (i=0;i<N;i++)
{
x[i]=10*i/N;
y[i]=10*(N-i-1)/N;
}
// Using x87
s=inner1(x,y,N);
printf("Result: %f\n",s);
// Using SSE
s=inner2(x,y,N);
printf("Result: %f\n",s);
_mm_free(x);
_mm_free(y);
return 0;
}
Задание.
1. Реализовать процедуру умножения квадратных матриц (размером кратным четырём) без использования специальных расширений и с использованием расширений SSE, сравнить время выполнения этих реализаций (Обязательное задание – 10 баллов).
2. В соответствии с вариантом задания реализовать матрично-векторную (с одинаковым размером матриц и векторов кратным четырём) процедуру с использованием расширений SSE (Дополнительное задание – 7 баллов).
3. С использованием инструкции cpuid определить наличие расширения SSE (Дополнительное задание – 3 балла).
4. Крайний срок сдачи – 7 мая 2011 года.
Варианты.
В предложенных вариантах предполагается, что
– скаляры,
– векторы,
– матрицы:
1. Операция
.
2. Операция
.
3. Операция
.
4. Операция
.
5. Операция
.
6. Операция
.
7. Операция
.
8. Операция
.
9. Операция
.
10. Операция
.






