/*-------------------------------------------------------------------*/ 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 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 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 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 */
/*-------------------------------------------------------------------*/ 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 */
/*------------------------------------------------------------------- * Function: Mat_vect_mult * Purpose: Multiply a matrix A by a vector x. The matrix is distributed * by block rows and the vectors are distributed by blocks * In args: local_A: calling process' rows of matrix A * local_x: calling process' components of vector x * local_m: calling process' number of rows * n: global (and local) number of columns * local_n: calling process' number of components of x * comm: communicator containing all calling processes * Errors: if malloc of local storage on any process fails, all * processes quit. * Notes: * 1. comm should be MPI_COMM_WORLD because of call to Check_for_errors * 2. local_m and local_n should be the same on all the processes */ void Mat_vect_mult( double local_A[] /* in */, double local_B[] /* in */, double local_C[] /* out */, int local_m /* in */, int n /* in */, int local_n /* in */, MPI_Comm comm /* in */) { double* x; double* col; int local_i, i, j; int local_ok = 1; x = malloc(n*sizeof(double)); col = malloc(local_n*sizeof(double)); if (x == NULL) local_ok = 0; Check_for_error(local_ok, "Mat_vect_mult", "Can't allocate temporary vector", comm); for(i = 0; i < n; i++) { for(j = 0; j < local_n; j++) { col[j] = local_B[j*n+i]; } MPI_Allgather(col, local_n, MPI_DOUBLE, x, local_n, MPI_DOUBLE, comm); for (local_i = 0; local_i < local_m; local_i++) { local_C[local_i*n+i] = 0.0; for (j = 0; j < n; j++) local_C[local_i*n+i] += local_A[local_i*n+j]*x[j]; } } free(col); free(x); } /* Mat_vect_mult */
/*-------------------------------------------------------------------*/ 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 */