Новости
О Центре
Кластер
Обучение
Основной курс по параллельному программированию
Учебные курсы
Магистратура
Дополнительное образование
Работы студентов
Библиотека
Исследования
Конференции
Полезные ссылки
NVIDIA
Контакты
О сайте
Имя:
Пароль:
запомнить:
Забыли пароль? Регистрация

Отчет

Отчет по лабораторной работе по курсу "Многопроцессорные вычислительные системы и параллельное программирование"

Тема "Решение системы СЛУ итеративным методом Якоби"

Выполнили студенты группы 84-10 Штыркова О.А., Сериков Е.В.

  1. Постановка задачи
  2. Дана система линейных уравнений:
    , где

    Или
    Для того, чтобы построить итеративную процедуру метода Якоби, необходимо провести предварительное преобразование системы уравнений к итерационному виду . Это преобразование осуществляется по следующему правилу:

    где в принятых обозначениях D означает матрицу, у которой на главной диагонали стоят соответствующие элементы матрицы A, а все остальные нули; тогда как матрицы U и L содержат верхнюю и нижнюю треугольные части A, на главной диагонали которых нули, E — единичная матрица. Тогда процедура нахождения решения имеет вид: где k счётчик итерации. Условие окончания итерационного процесса при достижении заданной точности имеет вид: .

  3. Описание схемы параллельной реализации
  4. Определим параллельную схему для реализации алгоритма решения поставленной задачи. На каждой k-ой итерации мы вычисляем k-ое приближение вектора решений. Компоненты вычисляемого вектора независимы между собой и их вычиление зависит только от компонент вектора, полученного не предыдущей итерации. Поэтому каждый узел будет параллельно вычислять свой компонент результирующего вектора (или несколько компонент). Затем все результаты вычислений будут пересылаться каждому узлу, так как вектор полученный на предыдущей итерации нужен для вычисления следующего приближения.

  5. Динамическая визуализация
  6. Теоретический анализ эффективности
  7. Время, затраченное на последовательное выполнение алгоритма, выражается следующей формулой: T = m * (2*n^2 - n), где m – число выполненных итераций, а n – число уравнений. Время, затраченное на параллельное выполнение алгоритма на p процессорах (без учета времени на передачу данных) выражается формулой: T(p) = m/p * (2*n^2 - n) Тогда ускорение равно: S = T(1) / T(p) = p Эффективность: E = T1 / p*Tp = 1 Определим затраты времени на передачу данных. Для этого используем модель Хокни. Первоначальная рассылка данных требует следующее время: Tcomm1 = (p-1) * (4*alfa + (n^2 / p + n) / betta) , где alfa - латентность, betta - пропускная способность сети. Передача данных, выполняемая в итерационном процессе, затрачивает следующее время: Tcomm2 = m * (p-1) * (3*alfa + (n / p + n) / betta) , где m - количество выполненных итераций. В итоге общее время передачи данных выражается формулой: Tcomm = (p-1) * (4*alfa + (n^2 / p + n) / betta) + k * (p-1) * (3*alfa + (n / p + n) / betta) Это время зависит от числа итераций. Как правило, их количество меньше числа уравнений n. Значит время на передачу данных можно оценить величиной: Tcomm = O(n^2) В свою очередь и ко времени выполнения алгоритма применима та же оценка: T = O(n^2) Если число итераций будет сравнимо с n, то для времени выполнения алгоритма будет справедлива уже другая оценка: T = O(n^3)

  8. Результаты проведенных экспериментов
  9. Характеристики используемой для рассчетов машины: Intel Core-i5-2410M CPU @ 2.3GHz, 4 GB RAM. Время работы алгортимов и ускорения представлены в таблице:
    Матрица Число итераций Последовательные (в 1 процесс) Параллельные в 2 процесса Ускорение при 2 процессаx Параллельные в 4 процесса Ускорение при 4 процессаx
    50x50 366 0,37 0,19 0,18 0,17 0,2
    100x100 744 3,1 1,5 1,6 1,4 1,7

  10. Исходный код программы
  11. #include "stdafx.h"
    #include "math.h"
    #include "windows.h"
    #include "stdio.h"
    #include "iostrea"
    #include "./include/mpi.h"
    #pragma comment(lib,"lib/i386/msmpi.lib")
    
    int      N      = 0;
    double   EPS    = 1; 
    double*  XS     = NULL;
    double*  X      = NULL;
    double** A      = NULL;
    double*  B      = NULL;
    void Jacobi (int rank);
    
    void initProcData( );
    void calc( int rank );
    int getRangeLen( int rank)
    {
        int size = 0;
        MPI_Comm_size( MPI_COMM_WORLD, &size);
        return (N/size)+((rank<(N-(N/size)*size))?1:0);
    }
    int getStartIndex(int rank)
    {
        int index = 0;
        for(int i = 0; i norm)
                        norm = fabs(X[h] - XS[h]);
                    XS[h] = X[h];
                }
    
            }while(norm>EPS);
            int flag = 0;
            
            for(int i = 1; i< size;i++)
            {
                MPI_Send(XS, N, MPI_DOUBLE, i, 99, MPI_COMM_WORLD);
                MPI_Send(&flag, 1, MPI_INT, i, 98, MPI_COMM_WORLD);
            }
    
            for(int i = 0; i< N;i++)
            {
                std::cout<< XS[i] <<",";
            }
    
        } 
        else                /* code for process one */ 
        {
            int flag = 0;
            do {
    
                MPI_Send(X+getStartIndex(rank), getRangeLen(rank), MPI_DOUBLE, 0, 99, MPI_COMM_WORLD);
                MPI_Recv(XS, N, MPI_DOUBLE, 0, 99, MPI_COMM_WORLD, &status); 
                MPI_Recv(&flag, 1, MPI_INT, 0, 98, MPI_COMM_WORLD, &status); 
                calc( rank );
    
            }while(flag);
        } 
    
    
        MPI_Finalize();
    
    
    }
    void calc( int rank )
    {
    
        Jacobi (rank);
    
    }
     
    void initProcData( )
    {
        char buf[256] = {0};
        char tmp[256] = {0};
        FILE *file = fopen("input.txt","r");
        if(!file)
            return;
        fgets(buf,256,file);
        N=atoi(buf);
        ZeroMemory(buf,256);
    
        fgets(buf,256,file);
        EPS=atof(buf);
        ZeroMemory(buf,256);
    
        XS = new double[N];
        X = new double[N];
        A = new double*[N];
        for(int i = 0; i< N;i++)
        {
            A[i] = new double[N];
        }
        B = new double[N];
    
        for(int i = 0; i< N;i++)
        {
            fgets(buf,256,file);
            char*softbuf = buf;
            if(strlen(buf) == 0)
                return;
            int len = strlen(buf);
            for(int k = 0; k< len; k++)
            {
                if( softbuf[k] == ',')
                    softbuf[k] = 0;
            }
            for(int j = 0; j< N; j++)
            {
                A[i][j] = atof(softbuf);
                softbuf += (strlen( softbuf )+1);
            }
            B[i] = atof(softbuf);
            ZeroMemory(buf,256);
        }
    
        fgets(buf,256,file);
        char*softbuf = buf;
        if(strlen(buf) == 0)
            return;
        int len = strlen(buf);
        for(int k = 0; k< len; k++)
        {
            if( softbuf[k] == ',')
                softbuf[k] = 0;
        }
        for(int j = 0; j< N; j++)
        {
            XS[j] = atof(softbuf);
            softbuf += (strlen( softbuf )+1);
        }
        ZeroMemory(buf,256);
    
        fclose(file);
       return;
    }
    
    void Jacobi (int rank)
    {
    
            for (int i = getStartIndex(rank); i< getStartIndex(rank)+getRangeLen(rank); i++) {
                X[i] =- B[i];
                for (int g = 0; g < N; g++) {
                    if (i != g)
                        X[i] += A[i][g] * XS[g];
                }
                X[i] /= -A[i][i];
            }
     }
    

Новости

22.10.2012
04.09.2012
05.04.2012
06.03.2012
02.03.2012