Использование SIMD расширений

Автор работы: Пользователь скрыл имя, 10 Мая 2013 в 15:04, лабораторная работа

Описание работы

1. Условие задачи:
Реализовать процедуру умножения квадратных матриц (размером кратным четырём):
1) без использования специальных расширений,
2) с использованием расширений SSE.
Сравнить время выполнения реализаций.
2. Условие задачи
В соответствии с вариантом задания реализовать матрично-векторную (с одинаковым размером матриц и векторов кратным четырём) процедуру с использованием расширений SSE.

Файлы: 1 файл

Otchyot_laba2.doc

— 70.00 Кб (Скачать файл)

Министерство  образования и науки Российской Федерации

 

«НОВОСИБИРСКИЙ ГОСУДАРСТВЕННЫЙ  ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

 

Факультет прикладной математики и информатики

Кафедра параллельных вычислительных технологий

 

 

 

 

 

Лабораторная  работа № 2

 

 

 

 

 

 

 

 

 

 

Выполнили:

Тонхоноев А.А.

 

студент 1 курса  ФПМИ,

группа ПМ-22

   
   

 

 

 

 

 

 

 

 

 

 

 

 

Новосибирск

2013 

  1. Условие задачи:

Реализовать процедуру  умножения квадратных матриц (размером кратным четырём):

  1. без использования специальных расширений,
  2. с использованием расширений SSE.

Сравнить время  выполнения реализаций.

 

 

  1. Текст программы

#include <xmmintrin.h>

#include <stdio.h>

#include <conio.h>

#include <locale.h>

#include <time.h>

#include <stdlib.h>

clock_t ns1;

void time_start();

long time_stop();

float skalar(float *x, float* y, int n);

float sseskalar(float* x, float* y, int n);

void mult(float **c, float **x, float **y, int m, int n, int q);

void mult2(float **c, float **x, float **y, int m, int n, int q);

int main()

{

setlocale(LC_ALL,"Russian");

 

FILE *fout1=fopen("output1.txt", "w");

FILE *fout2=fopen("output2.txt", "w");

int i,j,m,n,q;  long t; float z;

    printf("Умножение матриц А и В возможно только когда они размеров (m x n) и (n x q)\nВведите m, n, q:\n");

scanf("%d %d %d",&m,&n,&q);

 

 float **a=(float**)_mm_malloc(m*sizeof(float*),16);

 for(i=0; i<m; i++)

a[i]=(float*)_mm_malloc(n*sizeof(float),16);

 

for (i=0; i<m; i++)  //заполнение первой матрицы элементами

for (j=0; j<n; j++)

a[i][j]=(3*i+j+1);

 

 

float **b=(float**)_mm_malloc(n*sizeof(float*),16);

for(i=0; i<n; i++)

b[i]=(float*)_mm_malloc(q*sizeof(float),16);

 

for (i=0; i<n; ++i)  //заполнение второй матрицы элементами

 for (j=0; j<q; ++j)

b[i][j]=(i+1+2*j);

 

float **c=(float**)_mm_malloc(m*sizeof(float*),16);

for(i=0; i<n; i++)

c[i]=(float*)_mm_malloc(q*sizeof(float),16);

 

 

 

for (i=0; i<n; ++i) //транспонирование второй матрицы

 for (j=i; j<q; ++j)

 if (i!=j)

{

z=b[i][j];

b[i][j]=b[j][i];

b[j][i]=z;

}

time_start();

mult(c,a,b,m,n,q); //умножение матрицы без SIMD расширений

t=time_stop();

   for (i=0; i<n; ++i)

{

fprintf(fout1,"\n");

 for (j=0; j<q; ++j)

fprintf(fout1,"%f ", c[i][j]);

}

printf("\nВремя: %d\n", t);

 

time_start();

mult2(c,a,b,m,n,q); //умножение матрицы с использованием SSE

t=time_stop();

for (i=0; i<n; ++i)

{

fprintf(fout2,"\n");

 for (j=0; j<q; ++j)

fprintf(fout2, "%f ", c[i][j]);

}

    printf("\nВремя: %d\n", t);

getch();

 

_mm_free(a);

_mm_free(b);

_mm_free(c);

return 0;

fclose(fout1);

fclose(fout2);

}

float skalar(float *x, float* y, int n) //функция скалярного умножения векторов

{

  float s = 0;

  for(int i=0; i<n; i++)

    s += x[i]*y[i];

  return s;

}

float sseskalar(float* x, float* y, int n) //функция скалярного умножения векторов с использованием SSE

{

  __m128 *xx, *yy;

  __m128 p,s;

  xx = (__m128*)x;

  yy = (__m128*)y;

  s = _mm_set_ps1(0);

 

  for(int 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 = _mm_add_ps(s,p);

  p = _mm_shuffle_ps(s,s,1);

  s = _mm_add_ss(s,p);

 

  float sum;

  _mm_store_ss(&sum,s);

  return sum;

}

void mult(float **c, float **x, float **y, int m, int n, int q)

{

int i,j;

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

for (i=0; i<m; i++)

for (j=0; j<n; j++)

c[i][j]=skalar(x[i],y[j], n);

}

void mult2(float **c, float **x, float **y, int m, int n, int q)

{

int i,j;

 

for (i=0; i<m; i++)

for (j=0; j<n; j++)

c[i][j]=sseskalar(x[i],y[j], n);

}

void time_start()

  {

    ns1=clock();

  }

 

long time_stop()

  {

  return(clock()-ns1)*1000/CLOCKS_PER_SEC;

  }

 

  1. Условие задачи

В соответствии с вариантом задания реализовать  матрично-векторную (с одинаковым размером матриц и векторов кратным четырём) процедуру с использованием расширений SSE.

  (7) aAx+bBy

  1. Текст программы

 #include <xmmintrin.h>

#include <stdio.h>

#include <conio.h>

#include <locale.h>

#include <time.h>

#include <stdlib.h>

float sseskalar(float* x, float* y, int n) //функция скалярного умножения векторов с использованием SSE

{

  __m128 *xx, *yy;

  __m128 p,s;

  xx = (__m128*)x;

  yy = (__m128*)y;

  s = _mm_set_ps1(0);

 

  for(int 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 = _mm_add_ps(s,p);

  p = _mm_shuffle_ps(s,s,1);

  s = _mm_add_ss(s,p);

 

  float sum;

  _mm_store_ss(&sum,s);

  return sum;

}

void multvector(float *c, float **x, float *y, int m, int n) //умножение матрицы на вектор

{

int i;

 

for (i=0; i<m; i++)

c[i]=sseskalar(x[i], y, n);

}

void multconst(float *x, float alpha, int n) //умножение вектора на скаляр

{

for (int i=0; i<n; i++)

x[i]=x[i]*alpha;

}

void addict(float *x, float *y, int n) //сложение векторов

{

 for (int i=0; i<n; i++)

x[i]=x[i]+y[i];

}

void main()

{

//ax+bBy;

setlocale(LC_ALL,"Russian");

const int alpha=34.1, beta=12.4559;

FILE *fout1=fopen("output1.txt", "w");

FILE *fout2=fopen("output2.txt", "w");

int i,j,m,n;  long t; float z;

    printf("Введите m и n(размеры матриц, m так же задает размер вектора)\n");

scanf("%d %d",&m,&n);

 

 float **A=(float**)_mm_malloc(m*sizeof(float*),16);

 for(i=0; i<m; i++)

A[i]=(float*)_mm_malloc(n*sizeof(float),16);

 

for (i=0; i<m; i++)  //заполнение первой матрицы элементами

for (j=0; j<n; j++)

A[i][j]=(3*i+j+1)/2;

 

 

float **B=(float**)_mm_malloc(m*sizeof(float*),16);

for(i=0; i<n; i++)

B[i]=(float*)_mm_malloc(n*sizeof(float),16);

 

for (i=0; i<m; ++i)  //заполнение второй матрицы элементами

 for (j=0; j<n; ++j)

B[i][j]=(i+1+2*j)/3;

 

float *s1=(float*)_mm_malloc(m*sizeof(float),16);

float *s2=(float*)_mm_malloc(m*sizeof(float),16);

 

float *x=(float*)_mm_malloc(m*sizeof(float),16); //заполнение вектора

for (j=0; j<n; j++)

x[j]=(j+17)/15;

float *y=(float*)_mm_malloc(m*sizeof(float),16); //заполнение вектора

for (j=0; j<n; j++)

y[j]=(2*j+1)/23;

 

 

multvector(s2, B, y, m, n);

multconst(x,alpha, m);

multconst(s2,beta, m);

    addict(x,s2,m);

 

for(i=0; i<m; i++)

printf("%f ", x[i]);

 

getch();

_mm_free(A);

_mm_free(B);

_mm_free(s1);

_mm_free(s2);

_mm_free(x);

_mm_free(y);

}

 

  1. Вывод

На основании проделанной  работы можно сделать вывод, что  использование SIMD расширений ускоряет работу программы, однако эффективно лишь для множественных одинаковых операций над многими числами одновременно.


 


Информация о работе Использование SIMD расширений