All pastes #896707 Raw Edit

Mine

public text v1 · immutable
·published 2008-02-08 22:03 UTC
rendered paste body
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <mpi.h>

#define MASTER 0

#define DIVIDE 111
#define UNIFY 222

int total_procs, my_id;

typedef struct {
	int cols;
	int rows;
	float *data;
} MATRIX;

MATRIX create_matrix( int rows, int cols ) {
	MATRIX m;

	m.rows = rows;
	m.cols = cols;

	m.data = ( float * ) malloc( sizeof( float ) * rows * cols );

	return m;
}

void show_matrix( MATRIX m ) {
	int i, j;
	
	for( i = 0; i < m.rows; i++ ) {
		for( j = 0; j < m.cols; j++ )
			printf( "%f ", m.data[i * m.cols + j] );
		printf( "\n" );
	}
}

void write_matrix( MATRIX m ) {
	int i, j;
	FILE *f = fopen( "OUTPUT", "w" );
	
	for( i = 0; i < m.rows; i++ ) {
		for( j = 0; j < m.cols; j++ )
			fprintf( f, "%f ", m.data[i * m.cols + j] );
		fprintf( f, "\n" );
	}
}

void read_matrix( char *path, MATRIX *mat ) {
	int i, j;

	char aux_string[50];
	char rows_string[10], cols_string[10];

	FILE *input_file = fopen( path, "r" );

	fgets( aux_string, 50, input_file );
	printf( "Leyendo la matriz: %s", aux_string );

	fgets( aux_string, 50, input_file );
	sscanf( aux_string, "%s %s", rows_string, cols_string );

	printf( "Dimension: %sx%s\n", rows_string, cols_string );

	*mat = create_matrix( atoi( rows_string ), atoi( cols_string ) );

	for( i = 0; i < mat->rows; i++ )
		for( j = 0; j < mat->cols; j++ )
			fscanf( input_file, "%f", &mat->data[i * mat->cols + j] );
	
}

void multiply_matrix( MATRIX *dest, MATRIX a, MATRIX b ) {
	int i, j, k;

	*dest = create_matrix( a.rows, b.cols );

	for( i = 0; i< a.rows; i++ )	{
		for( j = 0; j < b.cols; j++ ) {
			dest->data[i * b.cols + j] = 0;
			for( k = 0; k < a.cols; k++ )
				dest->data[i * b.cols + j] += a.data[i * a.cols + k] * b.data[k * b.cols + j];
		}
	}
}

void broadcast_matrix( MATRIX *m ) {
	int rows, cols;

	rows = m->rows;
	cols = m->cols;

	MPI_Bcast( &rows, 1, MPI_INT, MASTER, MPI_COMM_WORLD );
	MPI_Bcast( &cols, 1, MPI_INT, MASTER, MPI_COMM_WORLD );
	
	if( my_id == MASTER )
		MPI_Bcast( m->data, rows * cols, MPI_FLOAT, MASTER, MPI_COMM_WORLD );
	else {
		*m = create_matrix( rows, cols );
		MPI_Bcast( m->data, rows * cols, MPI_FLOAT, MASTER, MPI_COMM_WORLD );
	}
}

void SOR_matrix_divide_data( MATRIX mat1 , MATRIX mat2, MATRIX *partial_matrix) {
	MATRIX aux_matrix;
	MPI_Status status;
	int mod, div;
	int i, size, current_pos;
	int cols, rows;

	cols = mat1.cols;
	rows = mat1.rows;

	MPI_Bcast( &cols, 1, MPI_INT, MASTER, MPI_COMM_WORLD );
	MPI_Bcast( &rows, 1, MPI_INT, MASTER, MPI_COMM_WORLD );
	
	div = rows / total_procs;
	mod = rows % total_procs;

	if( my_id == MASTER ) {
		current_pos = div;
		
		aux_matrix = create_matrix( div, mat1.cols );
		memcpy( aux_matrix.data, mat1.data, sizeof( float ) * div * aux_matrix.cols );
		
		for( i = 1; i < total_procs; i++ ) {
			size = div;
			if( i <= mod )
				size++;

			if( size > 0 )
				MPI_Send( mat1.data + ( current_pos * mat1.cols ), size * mat1.cols, MPI_FLOAT, i, DIVIDE, MPI_COMM_WORLD );
			current_pos += size;
		}
	}
	else {
		if( my_id <= mod )
			div++;
		aux_matrix = create_matrix( div, cols );
		if( size > 0 )
			MPI_Recv( aux_matrix.data, aux_matrix.rows * aux_matrix.cols, MPI_FLOAT, MASTER, DIVIDE, MPI_COMM_WORLD, &status );
	}
	
	multiply_matrix( partial_matrix, aux_matrix, mat2 );
}

void SOR_unify_partials( MATRIX *result, MATRIX partial, int rows, int cols ) {
	MATRIX aux_matrix;
	MPI_Status status;
	int mod, div;
	int i, size, current_pos;

	if( my_id == MASTER ) {
		*result = create_matrix( rows, cols );

		div = result->rows / total_procs;
		mod = result->rows % total_procs;

		memcpy( result->data, partial.data, sizeof( float ) * partial.rows * partial.cols );

		current_pos = div;
		for( i = 1; i < total_procs; i++ ) {
			size = div;
			if( i<=mod )
				size++;

			if( size > 0 )
				MPI_Recv( result->data + ( current_pos * result->cols ), size * result->cols, MPI_FLOAT, i, UNIFY, MPI_COMM_WORLD, &status );

			current_pos += size;
		}
	}
	else {
		if( size > 0 )
			MPI_Send( partial.data, partial.rows * partial.cols, MPI_FLOAT, MASTER, UNIFY, MPI_COMM_WORLD );
	}
}

void init( int argc, char *argv[] ) {
	MPI_Init( &argc, &argv );
	MPI_Comm_size( MPI_COMM_WORLD, &total_procs );
	MPI_Comm_rank( MPI_COMM_WORLD, &my_id );
}

void read_from_files( MATRIX *mat1, MATRIX *mat2, char *argv[]) {
	if( my_id == MASTER ) {
		read_matrix( argv[1], mat1 );
		show_matrix( *mat1 );
		printf("\n");
		read_matrix( argv[2], mat2 );
		show_matrix( *mat2 );
	}
}

void show_result( MATRIX m ) {
	if( my_id == MASTER ) {
		printf( "\n" );
		printf( "Resultado :\n" );
		show_matrix( m );
		write_matrix( m );
	}
}

int main( int argc, char *argv[] ) {
	MATRIX mat1, mat2, partial, res;

	init( argc, argv );
	if( argc != 3 ) {
		if( my_id == MASTER )
			printf( "Uso del programa: nombre_del_ejecutable 1ra_matriz 2da_matriz\n" );

		exit(0);
	}
	read_from_files( &mat1, &mat2, argv );
	broadcast_matrix( &mat2 );
	SOR_matrix_divide_data( mat1, mat2, &partial );
	SOR_unify_partials( &res, partial, mat1.rows, mat2.cols );
	show_result( res );

	MPI_Finalize();

	return 0;
}