Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Параллельные вычисления

3.9K
26 октября 2007 года
АКМ
49 / / 07.06.2005
Есть задача - распараллелить вычисление значения определенного интеграла от заданной функции методом трапеции и оценить погрешность.
Использовать библиотеку MPich.

Вот текст программы:
Код:
#pragma comment( lib, "mpich.lib" )

#include "mpi.h"
#include "stdlib.h"
#include "stdio.h"
#include "math.h"

double function( double x ) {
    double f_x;
    f_x = x;
    return sin(f_x) + 1;
}

int main( int argc, char* argv[], int size, int rank ) {
    double a, b, dx, p;
    int n, i;
    long int my_n, r;
    double my_a, my_b, my_s = 0, my_ds = 0, s = 0, t1, t2;
   
    MPI_Status st;
    MPI_Init( &argc, &argv );

    MPI_Barrier( MPI_COMM_WORLD );
    t1 = MPI_Wtime();

    MPI_Comm_size( MPI_COMM_WORLD, &size ); // общее кол-во процессов
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );

    if( rank == 0 ) {                       // номер текущего процесса равен нулю
        FILE *fp;
        char s[100];
        if (( fp = fopen( "text.txt", "rt" ) ) == NULL ) {
            printf( "File not open!\n" );
            exit( 1 );
        }
        fgets( s, 99, fp );
        a = atof( s );
        fgets( s, 99, fp );
        b = atof( s );
        fgets( s, 99, fp );
        n = atoi( s );

        for( i = 1; i < size; i++ ) {       // отправляем значения длины отрезка и числа дробления во все процессы
            MPI_Send( &a, 1, MPI_DOUBLE, i, i,     MPI_COMM_WORLD );
            MPI_Send( &b, 1, MPI_DOUBLE, i, i * 2, MPI_COMM_WORLD );
            MPI_Send( &n, 1, MPI_INT,    i, i * 3, MPI_COMM_WORLD );
        }
    } else {                                // принимаем во всех процессах значения длины отрезка и числа дробления
            MPI_Recv( &a, 1, MPI_DOUBLE, 0, rank,     MPI_COMM_WORLD, &st );
            MPI_Recv( &b, 1, MPI_DOUBLE, 0, rank * 2, MPI_COMM_WORLD, &st );
            MPI_Recv( &n, 1, MPI_INT,    0, rank * 3, MPI_COMM_WORLD, &st );   
    }

    r = n % size;
    printf ( "size = %d, r = %d\n", size, r );

    dx = ( b - a ) / n;
    if( rank < r ) {                        // вычисляем значения концов отрезка и число дроблении
            my_n = n / size + 1;            // число отрезков dx в процессе
            my_a = a + rank * my_n * dx;    // начало рабочего отрезка в процессе
            my_b = my_a + dx * my_n;        // конец рабочего отрезка в процессе
    } else {
            my_n = n / size;
            my_a = a + r * dx * ( my_n + 1 ) + ( rank - r ) * my_n * dx;
            my_b = my_a + dx * my_n;
    }
   
    my_s = dx * ( function(my_a)/2 + function(my_b)/2 );
    for ( i = 1; i < my_n; i++ ) {
        my_s = my_s + dx* function(my_a+i*dx);// средний кусочек площади
    }
   
    if( rank > 0 ) {                        // отправляем вычисленное значение в нулевой процесс
            MPI_Send( &my_s, 1, MPI_DOUBLE, 0, rank, MPI_COMM_WORLD );
    } else {                                // получаем итоговый результат
        for( i = 1; i < size; i++ ) {
            MPI_Recv( &my_s, 1, MPI_DOUBLE, i, i, MPI_COMM_WORLD, &st );
            s = s + my_s;
        }
    }
   
    // погрешность
    p = ( 1.00 / ( 12.00 * n * n ) )* ( b - a )*( b - a )*( b - a );

    MPI_Barrier( MPI_COMM_WORLD );
    t2 = MPI_Wtime();
   
    if( rank == 0 ) {
        printf( "Значение интеграла функции на отрезке [%f, %f] равно %f. \nВремя работы %f\n", a, b, s, t2 - t1 );
        printf( "Погрешность вычислений: %f\n", p );
    }

    MPI_Finalize();
    return 0;
}


Значения начала, конца отрезка и числа дроблений берутся из текстового файла (a=0, b=4, n=3).

Программа выдает неверный результат.
Помогите, пожалуйста, исправить ошибку.
Компилятор - MS VS .NET.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог