Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ОТЧЕТ ПО СЕМЕСТРОВОЙ

.doc
Скачиваний:
20
Добавлен:
20.04.2015
Размер:
95.23 Кб
Скачать

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ

Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования «Кемеровский государственный университет»

Математический факультет

Кафедра ЮНЕСКО по новым информационным технологиям

ОТЧЕТ ПО СЕМЕСТРОВОЙ РАБОТЕ

ПО ДИСЦИПЛИНЕ

Многопроцессорные вычислительные системы и параллельное программирование”

«Задача о восьми ферзях»

студента 2 курса

Костромин Дмитрий Александрович

Направление 010400.62 – Прикладная математика и информатика

Преподаватель:

к-т физ.-мат.наук, доцент

С.В. Стуколов

_____________________

Работа защищена:

“____”_______________201_г.

с оценкой _____________

Кемерово 201_

СОДЕРЖАНИЕ

Введение 2

1. Постановка задачи 2

2. Последовательный алгоритм 2

3. Параллельный алгоритм 5

Заключение 8

Литература 8

Введение

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

1. Постановка задачи

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

2)Обнаружив часть решений, процессы должны передать их на 0-й процесс.

3)Программа должна найти все решения и завершить работу. Управляющий процесс должен все решения записать в файл результатов.

2. Последовательный алгоритм

В первой функции проверяется диагонали и вертикали, то есть два ферзя не могут находиться одновременно на одной диагонали или же вертикали.

Задача решается с помощью 8 циклов, которые перебирают все варианты установки ферзей, затем вариант расстановки проверяется функцией и если он соответствует условию выполнения, то решение записывается в виде массива цифр и счетчик решений увеличивается на Затем все решения записываются в файл. На экран выводится время затраченное на выполнение задачи.

#include <stdlib.h>

#include <math.h>

#include <stdio.h>

#include "mpi.h"

int F(int *v)//функция проверки диагоналей, горизонтали

{

int result=0;

int k1,k,i,j,l,x,y;

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

{

k=v[i];

k1=i;

for(l=i+1;l<8;l++)

{

if(k==v[l])

{

result+=1;

}

y=abs(k-v[l]);

x=abs(k1-l);

if(x==y)

{

result+=1;

}

}

}

return result;// возвращаем результат

}

void CopyArray(int g[][8],int *a,int count)//функция копирования массива

{

int i;

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

{

g[count][i]=a[i];// в цикле переписываем матрицу в массив

}

}

int main(int argc, char* argv[])

{

int size, rank;

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD,&size);

MPI_Comm_rank(MPI_COMM_WORLD,&rank);

int count=0;//счетчик

int m[8];//размер доски, в дальнейшем в 8-ми циклах это и будет наша шахматная доска

int global[100][8];// матрица размером 100 на 8, где 100 предположительное число решений, а 8 число ферзей

int a,b,c,d,e,f,g,h,rrr;

double t1,t2;

t1=MPI_Wtime();

for(a=0;a<=7;a++)//в этих циклах устанавливаем по очереди всех ферзей, то есть перебираем все варианты установки ферзей

{

m[0]=a;

for(b=0;b<=7;b++)

{

m[1]=b;

for(c=0;c<=7;c++)

{

m[2]=c;

for(d=0;d<=7;d++)

{

m[3]=d;

for(e=0;e<=7;e++)

{

m[4]=e;

for( f=0;f<=7;f++)

{

m[5]=f;

for(g=0;g<=7;g++)

{

m[6]=g;

for(h=0;h<=7;h++)

{

m[7]=h;

if (F(m)==0)

{

count++;

CopyArray(global,m,count);

}

}

}

}

}

}

}

}

}

t2=MPI_Wtime();

FILE*fp;

fp=fopen("int.txt","w");

int i,j,k,z;

int tmp=1;

for(i=1;i<=count;i++)

{

fprintf(fp,"%d)\n",tmp);

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

{

fprintf(fp," %d ",global[i][j]);// вывод всех найденных решений

}//fprintf(fp,"\n");

tmp++;

fprintf(fp,"\n");

}

fclose(fp);

printf("time=%f",t2-t1);

MPI_Finalize();

return 0;

}

TIME=7.728835

3. Параллельный алгоритм

Все то же что и в параллельной программе, но когда доходим до 8 циклов, я самый верхний записываю for(i=rank;i<=7;i+=size) тем самым выполнил распараллеливание, затем отсылаю с разных процессоров решения на 0 процессор. 0 процессор узнает размер и количество принимаемых данных и записывает их себе. Затем он выводит все решения на экран и время выполнения задачи.

MPI_Probe(int source,int tag,MPI_Comm comm,MPI_Status *status) - Определяет параметры полученного сообщения без его чтения

Входные параметры:

source

- номер процесса-отправителя;

tag

- идентификатор сообщения;

comm

- коммуникатор.

Выходные параметры:

status

- атрибуты опрошенного сообщения.

MPI_Get_count(MPI_Status *status, MPI_Datatype datatype,int *count) - Определяет число фактически полученных элементов сообщения

Входные параметры:

Status

- атрибуты принятого сообщения;

Datatype

- тип элементов принятого сообщения.

Выходные параметры:

count

- число полученных элементов.

MPI_Recv – Принимает сообщения

MPI_Send – Посылает сообщения

#include <stdio.h>

#include <math.h>

#include "mpi.h"

int F(int *v)

{

int result=0;

int k1,k,i,j,l,x,y;

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

{

k=v[i];

k1=i;

for(l=i+1;l<8;l++)

{

if(k==v[l]){result+=1;}

y=abs(k-v[l]);

x=abs(k1-l);

if(x==y){result+=1;}

}

}

return result;

}

void CopyArray(int g[][8],int *a,int count)

{

int i;

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

{

g[count][i]=a[i];

}

}

int main(int argc, char* argv[])

{

int size, rank;

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD,&size);

MPI_Comm_rank(MPI_COMM_WORLD,&rank);

int count=0;

int m[8];

int global[100][8];

int a,b,c,d,e,f,g,h,rrr;

rrr=rank;

double t1,t2;

t1=MPI_Wtime();

for(a=rrr;a<=7;a=a+size)

{

m[0]=a;

for(b=0;b<=7;b++)

{

m[1]=b;

for(c=0;c<=7;c++)

{

m[2]=c;

for(d=0;d<=7;d++)

{

m[3]=d;

for(e=0;e<=7;e++)

{

m[4]=e;

for( f=0;f<=7;f++)

{

m[5]=f;

for(g=0;g<=7;g++)

{

m[6]=g;

for(h=0;h<=7;h++)

{

m[7]=h;

if (F(m)==0)

{

count++;

CopyArray(global,m,count);

}

}

}

}

}

}

}

}

}

int allsol[8][92][8];

MPI_Status stat;

int counts[8];

if(rank!=0)

{

MPI_Send(global,(count+1)*8, MPI_INT,0,100, MPI_COMM_WORLD);

}

int i,j,k;

if(rank==0)

{

for(i=1;i<size;i++)

{

MPI_Probe(i,100,MPI_COMM_WORLD,&stat);

MPI_Get_count(&stat,MPI_INT,&counts[i]);

MPI_Recv(&allsol[i],counts[i],MPI_INT,i,100,MPI_COMM_WORLD,&stat);

}

int tmp=1;

for(i=1;i<=count;i++)

{

printf("%d)",tmp);

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

{

printf(" %d ",global[i][j]);

}

tmp++;

printf("\n");

}

for(k=1;k<size;k++)

{

printf("--------------------------------------------------------- \n \n \n");

for(i=1;i<counts[k]/8;i++)

{

printf("%d)",tmp);

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

{

printf(" %d ",allsol[k][i][j]);

}

tmp++;

printf("\n");

}

}

}

if (rank == 0)

{

printf("time=%f\n",t2-t1);

}

MPI_Finalize();

return 0;

}

Теоретические данные

N

Boost

Efficiency

2

4

1.999977

3.999996

99.9

99.9

Формулы по которым я считал ускорение и эффективность

S=[(8^8)*M] / [{(8^8*M)/N}+K]

K – число пересылок

E=(S/N)*100

N –число процессоров

M – количество операций в каждом цикле

Практические данные

N

Time

Boost

Efficiency

1

7.734924

2

3.888741

1.987490

99.4

4

1.945198

2.342558

99.3

Заключение

Как видно из результатов, распараллеливание помогает ускорить процесс, за счет распределения выполнения операций.

Литература

Презентации лекций и лабораторных занятий

8