1、编写程序
vim mpi_mat_vect_time.c
2、编译、运行OpenMP并行程序(MPI矩阵-向量乘法)
mpicc -g -Wall -o mpi_mat_vect_time mpi_mat_vect_time.c
mpiexec -n 4 ./mpi_mat_vect_time
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void Check_for_error(int local_ok, char fname[], char message[],
MPI_Comm comm);
void Get_dims(int* m_p, int* local_m_p, int* n_p, int* local_n_p,
int my_rank, int comm_sz, MPI_Comm comm);
void Allocate_arrays(double** local_A_pp, double** local_x_pp,
double** local_y_pp, int local_m, int n, int local_n,
MPI_Comm comm);
void Read_matrix(char prompt[], double local_A[], int m, int local_m,
int n, int my_rank, MPI_Comm comm);
void Read_vector(char prompt[], double local_vec[], int n, int local_n,
int my_rank, MPI_Comm comm);
void Generate_matrix(double local_A[], int local_m, int n);
void Generate_vector(double local_x[], int local_n);
void Print_matrix(char title[], double local_A[], int m, int local_m,
int n, int my_rank, MPI_Comm comm);
void Print_vector(char title[], double local_vec[], int n,
int local_n, int my_rank, MPI_Comm comm);
void Mat_vect_mult(double local_A[], double local_x[],
double local_y[], int local_m, int n, int local_n,
MPI_Comm comm);
/*-------------------------------------------------------------------*/
int main(void) {
double* local_A;
double* local_x;
double* local_y;
int m, local_m, n, local_n;
int my_rank, comm_sz;
MPI_Comm comm;
double start, finish, loc_elapsed, elapsed;
MPI_Init(NULL, NULL);
comm = MPI_COMM_WORLD;
MPI_Comm_size(comm, &comm_sz);
MPI_Comm_rank(comm, &my_rank);
Get_dims(&m, &local_m, &n, &local_n, my_rank, comm_sz, comm);
Allocate_arrays(&local_A, &local_x, &local_y, local_m, n, local_n, comm);
// Read_matrix("A", local_A, m, local_m, n, my_rank, comm);
srandom(my_rank);
Generate_matrix(local_A, local_m, n);
# ifdef DEBUG
Print_matrix("A", local_A, m, local_m, n, my_rank, comm);
# endif
// Read_vector("x", local_x, n, local_n, my_rank, comm);
Generate_vector(local_x, local_n);
# ifdef DEBUG
Print_vector("x", local_x, n, local_n, my_rank, comm);
# endif
MPI_Barrier(comm);
start = MPI_Wtime();
Mat_vect_mult(local_A, local_x, local_y, local_m, n, local_n, comm);
finish = MPI_Wtime();
loc_elapsed = finish-start;
MPI_Reduce(&loc_elapsed, &elapsed, 1, MPI_DOUBLE, MPI_MAX, 0, comm);
# ifdef DEBUG
Print_vector("y", local_y, m, local_m, my_rank, comm);
# endif
if (my_rank == 0)
printf("Elapsed time = %e\n", elapsed);
free(local_A);
free(local_x);
free(local_y);
MPI_Finalize();
return 0;
} /* main */
/*-------------------------------------------------------------------*/
void Check_for_error(
int local_ok /* in */,
char fname[] /* in */,
char message[] /* in */,
MPI_Comm comm /* in */) {
int ok;
MPI_Allreduce(&local_ok, &ok, 1, MPI_INT, MPI_MIN, comm);
if (ok == 0) {
int my_rank;
MPI_Comm_rank(comm, &my_rank);
if (my_rank == 0) {
fprintf(stderr, "Proc %d > In %s, %s\n", my_rank, fname,
message);
fflush(stderr);
}
MPI_Finalize();
exit(-1);
}
} /* Check_for_error */
/*-------------------------------------------------------------------*/
void Get_dims(
int* m_p /* out */,
int* local_m_p /* out */,
int* n_p /* out */,
int* local_n_p /* out */,
int my_rank /* in */,
int comm_sz /* in */,
MPI_Comm comm /* in */) {
int local_ok = 1;
if (my_rank == 0) {
printf("Enter the number of rows\n");
scanf("%d", m_p);
printf("Enter the number of columns\n");
scanf("%d", n_p);
}
MPI_Bcast(m_p, 1, MPI_INT, 0, comm);
MPI_Bcast(n_p, 1, MPI_INT, 0, comm);
if (*m_p <= 0 || *n_p <= 0 || *m_p % comm_sz != 0
|| *n_p % comm_sz != 0) local_ok = 0;
Check_for_error(local_ok, "Get_dims",
"m and n must be positive and evenly divisible by comm_sz",
comm);
*local_m_p = *m_p/comm_sz;
*local_n_p = *n_p/comm_sz;
} /* Get_dims */
/*-------------------------------------------------------------------*/
void Allocate_arrays(
double** local_A_pp /* out */,
double** local_x_pp /* out */,
double** local_y_pp /* out */,
int local_m /* in */,
int n /* in */,
int local_n /* in */,
MPI_Comm comm /* in */) {
int local_ok = 1;
*local_A_pp = malloc(local_m*n*sizeof(double));
*local_x_pp = malloc(local_n*sizeof(double));
*local_y_pp = malloc(local_m*sizeof(double));
if (*local_A_pp == NULL || local_x_pp == NULL ||
local_y_pp == NULL) local_ok = 0;
Check_for_error(local_ok, "Allocate_arrays",
"Can't allocate local arrays", comm);
} /* Allocate_arrays */
/*-------------------------------------------------------------------*/
void Read_matrix(
char prompt[] /* in */,
double local_A[] /* out */,
int m /* in */,
int local_m /* in */,
int n /* in */,
int my_rank /* in */,
MPI_Comm comm /* in */) {
double* A = NULL;
int local_ok = 1;
int i, j;
if (my_rank == 0) {
A = malloc(m*n*sizeof(double));
if (A == NULL) local_ok = 0;
Check_for_error(local_ok, "Read_matrix",
"Can't allocate temporary matrix", comm);
printf("Enter the matrix %s\n", prompt);
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
scanf("%lf", &A[i*n+j]);
MPI_Scatter(A, local_m*n, MPI_DOUBLE,
local_A, local_m*n, MPI_DOUBLE, 0, comm);
free(A);
} else {
Check_for_error(local_ok, "Read_matrix",
"Can't allocate temporary matrix", comm);
MPI_Scatter(A, local_m*n, MPI_DOUBLE,
local_A, local_m*n, MPI_DOUBLE, 0, comm);
}
} /* Read_matrix */
/*-------------------------------------------------------------------*/
void Read_vector(
char prompt[] /* in */,
double local_vec[] /* out */,
int n /* in */,
int local_n /* in */,
int my_rank /* in */,
MPI_Comm comm /* in */) {
double* vec = NULL;
int i, local_ok = 1;
if (my_rank == 0) {
vec = malloc(n*sizeof(double));
if (vec == NULL) local_ok = 0;
Check_for_error(local_ok, "Read_vector",
"Can't allocate temporary vector", comm);
printf("Enter the vector %s\n", prompt);
for (i = 0; i < n; i++)
scanf("%lf", &vec[i]);
MPI_Scatter(vec, local_n, MPI_DOUBLE,
local_vec, local_n, MPI_DOUBLE, 0, comm);
free(vec);
} else {
Check_for_error(local_ok, "Read_vector",
"Can't allocate temporary vector", comm);
MPI_Scatter(vec, local_n, MPI_DOUBLE,
local_vec, local_n, MPI_DOUBLE, 0, comm);
}
} /* Read_vector */
/*-------------------------------------------------------------------*/
void Generate_matrix(
double local_A[] /* out */,
int local_m /* in */,
int n /* in */) {
int i, j;
for (i = 0; i < local_m; i++)
for (j = 0; j < n; j++)
local_A[i*n + j] = ((double) random())/((double) RAND_MAX);
} /* Generate_matrix */
/*-------------------------------------------------------------------*/
void Generate_vector(
double local_x[] /* out */,
int local_n /* in */) {
int i;
for (i = 0; i < local_n; i++)
local_x[i] = ((double) random())/((double) RAND_MAX);
} /* Generate_vector */
/*-------------------------------------------------------------------*/
void Print_matrix(
char title[] /* in */,
double local_A[] /* in */,
int m /* in */,
int local_m /* in */,
int n /* in */,
int my_rank /* in */,
MPI_Comm comm /* in */) {
double* A = NULL;
int i, j, local_ok = 1;
if (my_rank == 0) {
A = malloc(m*n*sizeof(double));
if (A == NULL) local_ok = 0;
Check_for_error(local_ok, "Print_matrix",
"Can't allocate temporary matrix", comm);
MPI_Gather(local_A, local_m*n, MPI_DOUBLE,
A, local_m*n, MPI_DOUBLE, 0, comm);
printf("\nThe matrix %s\n", title);
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++)
printf("%f ", A[i*n+j]);
printf("\n");
}
printf("\n");
free(A);
} else {
Check_for_error(local_ok, "Print_matrix",
"Can't allocate temporary matrix", comm);
MPI_Gather(local_A, local_m*n, MPI_DOUBLE,
A, local_m*n, MPI_DOUBLE, 0, comm);
}
} /* Print_matrix */
/*-------------------------------------------------------------------*/
void Print_vector(
char title[] /* in */,
double local_vec[] /* in */,
int n /* in */,
int local_n /* in */,
int my_rank /* in */,
MPI_Comm comm /* in */) {
double* vec = NULL;
int i, local_ok = 1;
if (my_rank == 0) {
vec = malloc(n*sizeof(double));
if (vec == NULL) local_ok = 0;
Check_for_error(local_ok, "Print_vector",
"Can't allocate temporary vector", comm);
MPI_Gather(local_vec, local_n, MPI_DOUBLE,
vec, local_n, MPI_DOUBLE, 0, comm);
printf("\nThe vector %s\n", title);
for (i = 0; i < n; i++)
printf("%f ", vec[i]);
printf("\n");
free(vec);
} else {
Check_for_error(local_ok, "Print_vector",
"Can't allocate temporary vector", comm);
MPI_Gather(local_vec, local_n, MPI_DOUBLE,
vec, local_n, MPI_DOUBLE, 0, comm);
}
} /* Print_vector */
/*-------------------------------------------------------------------*/
void Mat_vect_mult(
double local_A[] /* in */,
double local_x[] /* in */,
double local_y[] /* out */,
int local_m /* in */,
int n /* in */,
int local_n /* in */,
MPI_Comm comm /* in */) {
double* x;
int local_i, j;
int local_ok = 1;
x = malloc(n*sizeof(double));
if (x == NULL) local_ok = 0;
Check_for_error(local_ok, "Mat_vect_mult",
"Can't allocate temporary vector", comm);
MPI_Allgather(local_x, local_n, MPI_DOUBLE,
x, local_n, MPI_DOUBLE, comm);
for (local_i = 0; local_i < local_m; local_i++) {
local_y[local_i] = 0.0;
for (j = 0; j < n; j++)
local_y[local_i] += local_A[local_i*n+j]*x[j];
}
free(x);
} /* Mat_vect_mult */

本文介绍了如何使用C语言和MPI库来编写并行的矩阵-向量乘法程序。通过`vim`创建源文件`mpi_mat_vect_time.c`,然后使用`mpicc`编译,并用`mpiexec`执行程序,分配4个进程进行计算。
&spm=1001.2101.3001.5002&articleId=121890099&d=1&t=3&u=2a2c27fc236444889486407f2a227d4e)
2155

被折叠的 条评论
为什么被折叠?



