<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic opemnp/mpi code for Matrix multiplication in Intel® MPI Library</title>
    <link>https://community.intel.com/t5/Intel-MPI-Library/opemnp-mpi-code-for-Matrix-multiplication/m-p/776925#M295</link>
    <description>Hi ,&lt;BR /&gt;I have this matrix multiplication code that works fine on MPI and I am trying to add Openmp directives to this code to make use of my quad-core resources, can someone please tell me where and what to add to this code to make it work for hybrid openmp/mpi. Can someone help please!&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;P&gt;#include &lt;STDIO.H&gt;&lt;/STDIO.H&gt;&lt;/P&gt;&lt;P&gt;#include &lt;MPI.H&gt;&lt;/MPI.H&gt;&lt;/P&gt;&lt;P&gt;#include &lt;MATH.H&gt;&lt;/MATH.H&gt;&lt;/P&gt;&lt;P&gt;#include &lt;STDLIB.H&gt;&lt;/STDLIB.H&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;typedef struct GridInfo {&lt;/P&gt;&lt;P&gt;int p; /* Total number of processes */&lt;/P&gt;&lt;P&gt;MPI_Comm comm; /* Communicator for entire grid */&lt;/P&gt;&lt;P&gt;MPI_Comm row_comm; /* Communicator for my row */&lt;/P&gt;&lt;P&gt;MPI_Comm col_comm; /* Communicator for my col */&lt;/P&gt;&lt;P&gt;int q; /* Order of grid */&lt;/P&gt;&lt;P&gt;int my_row; /* My row number */&lt;/P&gt;&lt;P&gt;int my_col; /* My column number */&lt;/P&gt;&lt;P&gt;int my_rank; /* My rank in the grid comm */&lt;/P&gt;&lt;P&gt;} GRID_INFO_T;&lt;/P&gt;&lt;P&gt;#define MAX 65536&lt;/P&gt;&lt;P&gt;#define RandVal rand()%10 // Value which filled the matrix&lt;/P&gt;&lt;P&gt;typedef struct LocalMatrix {&lt;/P&gt;&lt;P&gt;int n_bar;&lt;/P&gt;&lt;P&gt;#define Order(A) ((A)-&amp;gt;n_bar)&lt;/P&gt;&lt;P&gt;float entries[MAX];&lt;/P&gt;&lt;P&gt;#define Entry(A,i,j) (*(((A)-&amp;gt;entries) + ((A)-&amp;gt;n_bar)*(i) + (j))) // Adress arithmetics&lt;/P&gt;&lt;P&gt;} LOCAL_MATRIX_T;&lt;/P&gt;&lt;P&gt;/* Function Declarations */&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* Local_matrix_allocate(int n_bar); // Memory for matrix&lt;/P&gt;&lt;P&gt;void Free_local_matrix(LOCAL_MATRIX_T** local_A); // Free memory&lt;/P&gt;&lt;P&gt;void Generate_matrix(char* title, LOCAL_MATRIX_T* local_A, // Fills the matrix&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid, int n);&lt;/P&gt;&lt;P&gt;void Print_matrix(char* title, LOCAL_MATRIX_T* local_A, // Prints the matrix on stdout&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid, int n);&lt;/P&gt;&lt;P&gt;void Set_to_zero(LOCAL_MATRIX_T* local_A); // Fills the matrix with zeroes&lt;/P&gt;&lt;P&gt;void Local_matrix_multiply(LOCAL_MATRIX_T* local_A, // Local matrix multiply&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_B, LOCAL_MATRIX_T* local_C);&lt;/P&gt;&lt;P&gt;void Build_matrix_type(LOCAL_MATRIX_T* local_A); // Creation of new MPI type for matrix&lt;/P&gt;&lt;P&gt;MPI_Datatype local_matrix_mpi_t; // New MPI type for matrix&lt;/P&gt;&lt;P&gt;double Sequential_time(int n);&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* temp_mat;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;int main(int argc, char* argv[]) {&lt;/P&gt;&lt;P&gt;int p; // Number of processes&lt;/P&gt;&lt;P&gt;int my_rank; // Rank of process&lt;/P&gt;&lt;P&gt;GRID_INFO_T grid; // Grid info of process&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A;&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_B;&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_C;&lt;/P&gt;&lt;P&gt;int n; // Order of matrix&lt;/P&gt;&lt;P&gt;int n_bar; // Order of submatrix&lt;/P&gt;&lt;P&gt;double begin_time, end_time, interval_p, interval_s;&lt;/P&gt;&lt;P&gt;void Setup_grid(GRID_INFO_T* grid); // Setup the grid info of process&lt;/P&gt;&lt;P&gt;void Fox(int n, GRID_INFO_T* grid, LOCAL_MATRIX_T* local_A, // Fox`s algorithm&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_B, LOCAL_MATRIX_T* local_C);&lt;/P&gt;&lt;P&gt;MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;/P&gt;&lt;P&gt;MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;my_rank);&lt;/P&gt;&lt;P&gt;MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;p);&lt;/P&gt;&lt;P&gt;Setup_grid(&amp;amp;grid); // Setup the grid info of process&lt;/P&gt;&lt;P&gt;if (my_rank == 0) {&lt;/P&gt;&lt;P&gt;printf("Enter the matrices order: ");&lt;/P&gt;&lt;P&gt;fflush(stdout);&lt;/P&gt;&lt;P&gt;scanf("%d", &amp;amp;n);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;//Sending size to all processes&lt;/P&gt;&lt;P&gt;MPI_Bcast(&amp;amp;n, 1, MPI_INT, 0, MPI_COMM_WORLD);&lt;/P&gt;&lt;P&gt;n_bar = n/grid.q; // Size of submatrix&lt;/P&gt;&lt;P&gt;local_A = Local_matrix_allocate(n_bar); // Memory for submatrix A in each process&lt;/P&gt;&lt;P&gt;Order(local_A) = n_bar;&lt;/P&gt;&lt;P&gt;Generate_matrix("\\nGenerate A", local_A, &amp;amp;grid, n); // Only P(0) do this&lt;/P&gt;&lt;P&gt;Print_matrix("Matrix A =", local_A, &amp;amp;grid, n); // Only P(0) do this&lt;/P&gt;&lt;P&gt;local_B = Local_matrix_allocate(n_bar); // Memory for submatrix B in each process&lt;/P&gt;&lt;P&gt;Order(local_B) = n_bar;&lt;/P&gt;&lt;P&gt;Generate_matrix("\\nGenerate B", local_B, &amp;amp;grid, n); // Only P(0) do this&lt;/P&gt;&lt;P&gt;Print_matrix("Matrix B =", local_B, &amp;amp;grid, n); // Only P(0) do this&lt;/P&gt;&lt;P&gt;Build_matrix_type(local_A); // Struct type for submatrix (MPI)&lt;/P&gt;&lt;P&gt;temp_mat = Local_matrix_allocate(n_bar); // Memory for Temp matrix&lt;/P&gt;&lt;P&gt;local_C = Local_matrix_allocate(n_bar); // Memory for result matrix C&lt;/P&gt;&lt;P&gt;Order(local_C) = n_bar; // Size of C&lt;/P&gt;&lt;P&gt;begin_time = MPI_Wtime();&lt;/P&gt;&lt;P&gt;Fox(n, &amp;amp;grid, local_A, local_B, local_C); // Block-algoritm of FOX&lt;/P&gt;&lt;P&gt;end_time = MPI_Wtime();&lt;/P&gt;&lt;P&gt;Print_matrix("\\nThe product is:", local_C, &amp;amp;grid, n);&lt;/P&gt;&lt;P&gt;interval_p = end_time - begin_time;&lt;/P&gt;&lt;P&gt;if (my_rank == 0) {&lt;/P&gt;&lt;P&gt;/* Sequential matrix multiplication */&lt;/P&gt;&lt;P&gt;interval_s = Sequential_time(n);&lt;/P&gt;&lt;P&gt;/* Speed-up */&lt;/P&gt;&lt;P&gt;printf("\\nTp = %.10f", interval_p);&lt;/P&gt;&lt;P&gt;printf("\\nTs = %.10f", interval_s);&lt;/P&gt;&lt;P&gt;printf("\\nS = %.10f\\n\\n", interval_s/interval_p);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;Free_local_matrix(&amp;amp;local_A);&lt;/P&gt;&lt;P&gt;Free_local_matrix(&amp;amp;local_B);&lt;/P&gt;&lt;P&gt;Free_local_matrix(&amp;amp;local_C);&lt;/P&gt;&lt;P&gt;return MPI_Finalize();&lt;/P&gt;&lt;P&gt;} /* main */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Setup_grid(&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid /* out */) {&lt;/P&gt;&lt;P&gt;int old_rank;&lt;/P&gt;&lt;P&gt;int dimensions[2];&lt;/P&gt;&lt;P&gt;int wrap_around[2];&lt;/P&gt;&lt;P&gt;int coordinates[2];&lt;/P&gt;&lt;P&gt;int free_coords[2];&lt;/P&gt;&lt;P&gt;/* Set up Global Grid Information */&lt;/P&gt;&lt;P&gt;MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;(grid-&amp;gt;p));&lt;/P&gt;&lt;P&gt;MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;old_rank);&lt;/P&gt;&lt;P&gt;/* We assume p is a perfect square */&lt;/P&gt;&lt;P&gt;grid-&amp;gt;q = (int) sqrt((double) grid-&amp;gt;p);&lt;/P&gt;&lt;P&gt;dimensions[0] = dimensions[1] = grid-&amp;gt;q;&lt;/P&gt;&lt;P&gt;/* We want a circular shift in second dimension. */&lt;/P&gt;&lt;P&gt;/* Don't care about first */&lt;/P&gt;&lt;P&gt;wrap_around[0] = wrap_around[1] = 1;&lt;/P&gt;&lt;P&gt;MPI_Cart_create(MPI_COMM_WORLD, 2, dimensions, wrap_around, 1, &amp;amp;(grid-&amp;gt;comm));&lt;/P&gt;&lt;P&gt;MPI_Comm_rank(grid-&amp;gt;comm, &amp;amp;(grid-&amp;gt;my_rank));&lt;/P&gt;&lt;P&gt;MPI_Cart_coords(grid-&amp;gt;comm, grid-&amp;gt;my_rank, 2, coordinates);&lt;/P&gt;&lt;P&gt;grid-&amp;gt;my_row = coordinates[0];&lt;/P&gt;&lt;P&gt;grid-&amp;gt;my_col = coordinates[1];&lt;/P&gt;&lt;P&gt;/* Set up row communicators */&lt;/P&gt;&lt;P&gt;free_coords[0] = 0;&lt;/P&gt;&lt;P&gt;free_coords[1] = 1;&lt;/P&gt;&lt;P&gt;MPI_Cart_sub(grid-&amp;gt;comm, free_coords, &amp;amp;(grid-&amp;gt;row_comm));&lt;/P&gt;&lt;P&gt;/* Set up column communicators */&lt;/P&gt;&lt;P&gt;free_coords[0] = 1;&lt;/P&gt;&lt;P&gt;free_coords[1] = 0;&lt;/P&gt;&lt;P&gt;MPI_Cart_sub(grid-&amp;gt;comm, free_coords, &amp;amp;(grid-&amp;gt;col_comm));&lt;/P&gt;&lt;P&gt;} /* Setup_grid */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Fox(&lt;/P&gt;&lt;P&gt;int n /* in */,&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_B /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_C /* out */) {&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* temp_A; /* Storage for the sub- */&lt;/P&gt;&lt;P&gt;/* matrix of A used during */&lt;/P&gt;&lt;P&gt;/* the current stage */&lt;/P&gt;&lt;P&gt;int stage;&lt;/P&gt;&lt;P&gt;int bcast_root;&lt;/P&gt;&lt;P&gt;int n_bar; /* n/sqrt(p) */&lt;/P&gt;&lt;P&gt;int source;&lt;/P&gt;&lt;P&gt;int dest;&lt;/P&gt;&lt;P&gt;MPI_Status status;&lt;/P&gt;&lt;P&gt;n_bar = n/grid-&amp;gt;q;&lt;/P&gt;&lt;P&gt;Set_to_zero(local_C);&lt;/P&gt;&lt;P&gt;/* Calculate addresses for circular shift of B */&lt;/P&gt;&lt;P&gt;source = (grid-&amp;gt;my_row + 1) % grid-&amp;gt;q; // (l + 1) mod q&lt;/P&gt;&lt;P&gt;dest = (grid-&amp;gt;my_row + grid-&amp;gt;q - 1) % grid-&amp;gt;q; // (l + q - 1) mod q&lt;/P&gt;&lt;P&gt;/* Set aside storage for the broadcast block of A */&lt;/P&gt;&lt;P&gt;temp_A = Local_matrix_allocate(n_bar);&lt;/P&gt;&lt;P&gt;for (stage = 0; stage &amp;lt; grid-&amp;gt;q; stage++) {&lt;/P&gt;&lt;P&gt;bcast_root = (grid-&amp;gt;my_row + stage) % grid-&amp;gt;q; // (l + stage) mod q --&amp;gt; (n)&lt;/P&gt;&lt;P&gt;if (bcast_root == grid-&amp;gt;my_col) { // if (n == k)&lt;/P&gt;&lt;P&gt;MPI_Bcast(local_A, 1, local_matrix_mpi_t, // Broadcasting of A[l,k] (sub-block)&lt;/P&gt;&lt;P&gt;bcast_root, grid-&amp;gt;row_comm);&lt;/P&gt;&lt;P&gt;Local_matrix_multiply(local_A, local_B, // C[l,k] += (A[l,n] * B[n,k])&lt;/P&gt;&lt;P&gt;local_C);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;else {&lt;/P&gt;&lt;P&gt;MPI_Bcast(temp_A, 1, local_matrix_mpi_t,&lt;/P&gt;&lt;P&gt;bcast_root, grid-&amp;gt;row_comm);&lt;/P&gt;&lt;P&gt;Local_matrix_multiply(temp_A, local_B,&lt;/P&gt;&lt;P&gt;local_C);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;MPI_Sendrecv_replace(local_B, 1, local_matrix_mpi_t, //Sends and receives using a single buffer&lt;/P&gt;&lt;P&gt;dest, 0/* sendtag*/, source, 0/*recvtag*/, grid-&amp;gt;col_comm, &amp;amp;status);&lt;/P&gt;&lt;P&gt;} /* for */&lt;/P&gt;&lt;P&gt;} /* Fox */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* Local_matrix_allocate(int local_order) {&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* temp;&lt;/P&gt;&lt;P&gt;temp = (LOCAL_MATRIX_T*) malloc(sizeof(LOCAL_MATRIX_T));&lt;/P&gt;&lt;P&gt;return temp;&lt;/P&gt;&lt;P&gt;} /* Local_matrix_allocate */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Free_local_matrix(&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T** local_A_ptr /* in/out */) {&lt;/P&gt;&lt;P&gt;free(*local_A_ptr);&lt;/P&gt;&lt;P&gt;} /* Free_local_matrix */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;/* Read and distribute matrix:&lt;/P&gt;&lt;P&gt;* foreach global row of the matrix,&lt;/P&gt;&lt;P&gt;* foreach grid column&lt;/P&gt;&lt;P&gt;* read a block of n_bar floats on process 0&lt;/P&gt;&lt;P&gt;* and send them to the appropriate process.&lt;/P&gt;&lt;P&gt;*/&lt;/P&gt;&lt;P&gt;void Generate_matrix(&lt;/P&gt;&lt;P&gt;char* title /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* out */,&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid /* in */,&lt;/P&gt;&lt;P&gt;int n /* in */) {&lt;/P&gt;&lt;P&gt;int mat_row, mat_col;&lt;/P&gt;&lt;P&gt;int grid_row, grid_col;&lt;/P&gt;&lt;P&gt;int dest;&lt;/P&gt;&lt;P&gt;int coords[2];&lt;/P&gt;&lt;P&gt;float* temp;&lt;/P&gt;&lt;P&gt;MPI_Status status;&lt;/P&gt;&lt;P&gt;if (grid-&amp;gt;my_rank == 0) {&lt;/P&gt;&lt;P&gt;//printf("%d\\n", grid-&amp;gt;my_rank);&lt;/P&gt;&lt;P&gt;temp = (float*) malloc(Order(local_A)*sizeof(float));&lt;/P&gt;&lt;P&gt;printf("%s\\n", title);&lt;/P&gt;&lt;P&gt;fflush(stdout);&lt;/P&gt;&lt;P&gt;for (mat_row = 0; mat_row &amp;lt; n; mat_row++) {&lt;/P&gt;&lt;P&gt;grid_row = mat_row/Order(local_A);&lt;/P&gt;&lt;P&gt;coords[0] = grid_row;&lt;/P&gt;&lt;P&gt;for (grid_col = 0; grid_col &amp;lt; grid-&amp;gt;q; grid_col++) {&lt;/P&gt;&lt;P&gt;coords[1] = grid_col;&lt;/P&gt;&lt;P&gt;MPI_Cart_rank(grid-&amp;gt;comm, coords, &amp;amp;dest);&lt;/P&gt;&lt;P&gt;if (dest == 0) {&lt;/P&gt;&lt;P&gt;for (mat_col = 0; mat_col &amp;lt; Order(local_A); mat_col++)&lt;/P&gt;&lt;P&gt;//scanf("%f", (local_A-&amp;gt;entries)+mat_row*Order(local_A)+mat_col);&lt;/P&gt;&lt;P&gt;*((local_A-&amp;gt;entries)+mat_row*Order(local_A)+mat_col) = RandVal;&lt;/P&gt;&lt;P&gt;} else {&lt;/P&gt;&lt;P&gt;for(mat_col = 0; mat_col &amp;lt; Order(local_A); mat_col++)&lt;/P&gt;&lt;P&gt;//scanf("%f", temp + mat_col);&lt;/P&gt;&lt;P&gt;*(temp + mat_col) = RandVal;&lt;/P&gt;&lt;P&gt;MPI_Send(temp, Order(local_A), MPI_FLOAT, dest, 0,&lt;/P&gt;&lt;P&gt;grid-&amp;gt;comm);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;free(temp);&lt;/P&gt;&lt;P&gt;} else {&lt;/P&gt;&lt;P&gt;for (mat_row = 0; mat_row &amp;lt; Order(local_A); mat_row++)&lt;/P&gt;&lt;P&gt;MPI_Recv(&amp;amp;Entry(local_A, mat_row, 0), Order(local_A),&lt;/P&gt;&lt;P&gt;MPI_FLOAT, 0, 0, grid-&amp;gt;comm, &amp;amp;status);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;} /* Read_matrix */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Print_matrix(&lt;/P&gt;&lt;P&gt;char* title /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* out */,&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid /* in */,&lt;/P&gt;&lt;P&gt;int n /* in */) {&lt;/P&gt;&lt;P&gt;int mat_row, mat_col;&lt;/P&gt;&lt;P&gt;int grid_row, grid_col;&lt;/P&gt;&lt;P&gt;int source;&lt;/P&gt;&lt;P&gt;int coords[2];&lt;/P&gt;&lt;P&gt;float* temp;&lt;/P&gt;&lt;P&gt;MPI_Status status;&lt;/P&gt;&lt;P&gt;if (grid-&amp;gt;my_rank == 0) {&lt;/P&gt;&lt;P&gt;temp = (float*) malloc(Order(local_A)*sizeof(float));&lt;/P&gt;&lt;P&gt;printf("%s\\n", title);&lt;/P&gt;&lt;P&gt;for (mat_row = 0; mat_row &amp;lt; n; mat_row++) {&lt;/P&gt;&lt;P&gt;grid_row = mat_row/Order(local_A);&lt;/P&gt;&lt;P&gt;coords[0] = grid_row;&lt;/P&gt;&lt;P&gt;for (grid_col = 0; grid_col &amp;lt; grid-&amp;gt;q; grid_col++) {&lt;/P&gt;&lt;P&gt;coords[1] = grid_col;&lt;/P&gt;&lt;P&gt;MPI_Cart_rank(grid-&amp;gt;comm, coords, &amp;amp;source);&lt;/P&gt;&lt;P&gt;if (source == 0) {&lt;/P&gt;&lt;P&gt;for(mat_col = 0; mat_col &amp;lt; Order(local_A); mat_col++)&lt;/P&gt;&lt;P&gt;printf("%6.1f ", Entry(local_A, mat_row, mat_col));&lt;/P&gt;&lt;P&gt;} else {&lt;/P&gt;&lt;P&gt;MPI_Recv(temp, Order(local_A), MPI_FLOAT, source, 0,&lt;/P&gt;&lt;P&gt;grid-&amp;gt;comm, &amp;amp;status);&lt;/P&gt;&lt;P&gt;for(mat_col = 0; mat_col &amp;lt; Order(local_A); mat_col++)&lt;/P&gt;&lt;P&gt;printf("%6.1f ", temp[mat_col]);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;printf("\\n");&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;free(temp);&lt;/P&gt;&lt;P&gt;} else {&lt;/P&gt;&lt;P&gt;for (mat_row = 0; mat_row &amp;lt; Order(local_A); mat_row++)&lt;/P&gt;&lt;P&gt;MPI_Send(&amp;amp;Entry(local_A, mat_row, 0), Order(local_A),&lt;/P&gt;&lt;P&gt;MPI_FLOAT, 0, 0, grid-&amp;gt;comm);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;} /* Print_matrix */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Set_to_zero(&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* out */) {&lt;/P&gt;&lt;P&gt;int i, j;&lt;/P&gt;&lt;P&gt;for (i = 0; i &amp;lt; Order(local_A); i++)&lt;/P&gt;&lt;P&gt;for (j = 0; j &amp;lt; Order(local_A); j++)&lt;/P&gt;&lt;P&gt;Entry(local_A,i,j) = 0.0;&lt;/P&gt;&lt;P&gt;} /* Set_to_zero */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Build_matrix_type(&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* in */) {&lt;/P&gt;&lt;P&gt;MPI_Datatype temp_mpi_t;&lt;/P&gt;&lt;P&gt;int block_lengths[2];&lt;/P&gt;&lt;P&gt;MPI_Aint displacements[2];&lt;/P&gt;&lt;P&gt;MPI_Datatype typelist[2];&lt;/P&gt;&lt;P&gt;MPI_Aint start_address;&lt;/P&gt;&lt;P&gt;MPI_Aint address;&lt;/P&gt;&lt;P&gt;MPI_Type_contiguous(Order(local_A)*Order(local_A),&lt;/P&gt;&lt;P&gt;MPI_FLOAT, &amp;amp;temp_mpi_t); //array[0..n-1,0..n-1] of float&lt;/P&gt;&lt;P&gt;block_lengths[0] = block_lengths[1] = 1;&lt;/P&gt;&lt;P&gt;typelist[0] = MPI_INT; //2 elements: 1) int, 2) array[...] of float&lt;/P&gt;&lt;P&gt;typelist[1] = temp_mpi_t;&lt;/P&gt;&lt;P&gt;MPI_Address(local_A, &amp;amp;start_address); //adress of submatrix - start&lt;/P&gt;&lt;P&gt;MPI_Address(&amp;amp;(local_A-&amp;gt;n_bar), &amp;amp;address); //adress of Size of submatrix&lt;/P&gt;&lt;P&gt;displacements[0] = address - start_address; //between n_bar and beginning (sometimes &amp;lt;&amp;gt;0 )&lt;/P&gt;&lt;P&gt;MPI_Address(local_A-&amp;gt;entries, &amp;amp;address); //adress of entries&lt;/P&gt;&lt;P&gt;displacements[1] = address - start_address; //between entries and beginning&lt;/P&gt;&lt;P&gt;MPI_Type_struct(2, block_lengths, displacements, //new struct type&lt;/P&gt;&lt;P&gt;typelist, &amp;amp;local_matrix_mpi_t);&lt;/P&gt;&lt;P&gt;MPI_Type_commit(&amp;amp;local_matrix_mpi_t); //return type?&lt;/P&gt;&lt;P&gt;} /* Build_matrix_type */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Local_matrix_multiply(&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_B /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_C /* out */) {&lt;/P&gt;&lt;P&gt;int i, j, k;&lt;/P&gt;&lt;P&gt;for (i = 0; i &amp;lt; Order(local_A); i++)&lt;/P&gt;&lt;P&gt;for (j = 0; j &amp;lt; Order(local_A); j++)&lt;/P&gt;&lt;P&gt;for (k = 0; k &amp;lt; Order(local_B); k++)&lt;/P&gt;&lt;P&gt;Entry(local_C,i,j) += Entry(local_A,i,k)*Entry(local_B,k,j);&lt;/P&gt;&lt;P&gt;} /* Local_matrix_multiply */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;double Sequential_time(int n) {&lt;/P&gt;&lt;P&gt;int i,j,k;&lt;/P&gt;&lt;P&gt;double begin_time, end_time;&lt;/P&gt;&lt;P&gt;float *A = (float *) malloc(n*n * sizeof(float));&lt;/P&gt;&lt;P&gt;float* B = (float *) malloc(n*n * sizeof(float));&lt;/P&gt;&lt;P&gt;float* C = (float *) malloc(n*n * sizeof(float));&lt;/P&gt;&lt;P&gt;for (i=0; i&lt;N&gt;&lt;/N&gt;&lt;/P&gt;&lt;P&gt;A&lt;I&gt; = RandVal; B&lt;I&gt; = RandVal; C&lt;I&gt; = 0.0;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;begin_time = MPI_Wtime();&lt;/P&gt;&lt;P&gt;for (i = 0; i &amp;lt; n; i++) {&lt;/P&gt;&lt;P&gt;for (j = 0; j &amp;lt; n; j++) {&lt;/P&gt;&lt;P&gt;for (k = 0; k &amp;lt; n; k++) {&lt;/P&gt;&lt;P&gt;C[i*n+j] += A[i*n+k]*B[k*n+j];&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;end_time = MPI_Wtime();&lt;/P&gt;&lt;P&gt;free(A); free(B); free(C);&lt;/P&gt;&lt;P&gt;return end_time - begin_time;&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;</description>
    <pubDate>Wed, 23 Mar 2011 18:48:24 GMT</pubDate>
    <dc:creator>dusear4la</dc:creator>
    <dc:date>2011-03-23T18:48:24Z</dc:date>
    <item>
      <title>opemnp/mpi code for Matrix multiplication</title>
      <link>https://community.intel.com/t5/Intel-MPI-Library/opemnp-mpi-code-for-Matrix-multiplication/m-p/776925#M295</link>
      <description>Hi ,&lt;BR /&gt;I have this matrix multiplication code that works fine on MPI and I am trying to add Openmp directives to this code to make use of my quad-core resources, can someone please tell me where and what to add to this code to make it work for hybrid openmp/mpi. Can someone help please!&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;P&gt;#include &lt;STDIO.H&gt;&lt;/STDIO.H&gt;&lt;/P&gt;&lt;P&gt;#include &lt;MPI.H&gt;&lt;/MPI.H&gt;&lt;/P&gt;&lt;P&gt;#include &lt;MATH.H&gt;&lt;/MATH.H&gt;&lt;/P&gt;&lt;P&gt;#include &lt;STDLIB.H&gt;&lt;/STDLIB.H&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;typedef struct GridInfo {&lt;/P&gt;&lt;P&gt;int p; /* Total number of processes */&lt;/P&gt;&lt;P&gt;MPI_Comm comm; /* Communicator for entire grid */&lt;/P&gt;&lt;P&gt;MPI_Comm row_comm; /* Communicator for my row */&lt;/P&gt;&lt;P&gt;MPI_Comm col_comm; /* Communicator for my col */&lt;/P&gt;&lt;P&gt;int q; /* Order of grid */&lt;/P&gt;&lt;P&gt;int my_row; /* My row number */&lt;/P&gt;&lt;P&gt;int my_col; /* My column number */&lt;/P&gt;&lt;P&gt;int my_rank; /* My rank in the grid comm */&lt;/P&gt;&lt;P&gt;} GRID_INFO_T;&lt;/P&gt;&lt;P&gt;#define MAX 65536&lt;/P&gt;&lt;P&gt;#define RandVal rand()%10 // Value which filled the matrix&lt;/P&gt;&lt;P&gt;typedef struct LocalMatrix {&lt;/P&gt;&lt;P&gt;int n_bar;&lt;/P&gt;&lt;P&gt;#define Order(A) ((A)-&amp;gt;n_bar)&lt;/P&gt;&lt;P&gt;float entries[MAX];&lt;/P&gt;&lt;P&gt;#define Entry(A,i,j) (*(((A)-&amp;gt;entries) + ((A)-&amp;gt;n_bar)*(i) + (j))) // Adress arithmetics&lt;/P&gt;&lt;P&gt;} LOCAL_MATRIX_T;&lt;/P&gt;&lt;P&gt;/* Function Declarations */&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* Local_matrix_allocate(int n_bar); // Memory for matrix&lt;/P&gt;&lt;P&gt;void Free_local_matrix(LOCAL_MATRIX_T** local_A); // Free memory&lt;/P&gt;&lt;P&gt;void Generate_matrix(char* title, LOCAL_MATRIX_T* local_A, // Fills the matrix&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid, int n);&lt;/P&gt;&lt;P&gt;void Print_matrix(char* title, LOCAL_MATRIX_T* local_A, // Prints the matrix on stdout&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid, int n);&lt;/P&gt;&lt;P&gt;void Set_to_zero(LOCAL_MATRIX_T* local_A); // Fills the matrix with zeroes&lt;/P&gt;&lt;P&gt;void Local_matrix_multiply(LOCAL_MATRIX_T* local_A, // Local matrix multiply&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_B, LOCAL_MATRIX_T* local_C);&lt;/P&gt;&lt;P&gt;void Build_matrix_type(LOCAL_MATRIX_T* local_A); // Creation of new MPI type for matrix&lt;/P&gt;&lt;P&gt;MPI_Datatype local_matrix_mpi_t; // New MPI type for matrix&lt;/P&gt;&lt;P&gt;double Sequential_time(int n);&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* temp_mat;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;int main(int argc, char* argv[]) {&lt;/P&gt;&lt;P&gt;int p; // Number of processes&lt;/P&gt;&lt;P&gt;int my_rank; // Rank of process&lt;/P&gt;&lt;P&gt;GRID_INFO_T grid; // Grid info of process&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A;&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_B;&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_C;&lt;/P&gt;&lt;P&gt;int n; // Order of matrix&lt;/P&gt;&lt;P&gt;int n_bar; // Order of submatrix&lt;/P&gt;&lt;P&gt;double begin_time, end_time, interval_p, interval_s;&lt;/P&gt;&lt;P&gt;void Setup_grid(GRID_INFO_T* grid); // Setup the grid info of process&lt;/P&gt;&lt;P&gt;void Fox(int n, GRID_INFO_T* grid, LOCAL_MATRIX_T* local_A, // Fox`s algorithm&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_B, LOCAL_MATRIX_T* local_C);&lt;/P&gt;&lt;P&gt;MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;/P&gt;&lt;P&gt;MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;my_rank);&lt;/P&gt;&lt;P&gt;MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;p);&lt;/P&gt;&lt;P&gt;Setup_grid(&amp;amp;grid); // Setup the grid info of process&lt;/P&gt;&lt;P&gt;if (my_rank == 0) {&lt;/P&gt;&lt;P&gt;printf("Enter the matrices order: ");&lt;/P&gt;&lt;P&gt;fflush(stdout);&lt;/P&gt;&lt;P&gt;scanf("%d", &amp;amp;n);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;//Sending size to all processes&lt;/P&gt;&lt;P&gt;MPI_Bcast(&amp;amp;n, 1, MPI_INT, 0, MPI_COMM_WORLD);&lt;/P&gt;&lt;P&gt;n_bar = n/grid.q; // Size of submatrix&lt;/P&gt;&lt;P&gt;local_A = Local_matrix_allocate(n_bar); // Memory for submatrix A in each process&lt;/P&gt;&lt;P&gt;Order(local_A) = n_bar;&lt;/P&gt;&lt;P&gt;Generate_matrix("\\nGenerate A", local_A, &amp;amp;grid, n); // Only P(0) do this&lt;/P&gt;&lt;P&gt;Print_matrix("Matrix A =", local_A, &amp;amp;grid, n); // Only P(0) do this&lt;/P&gt;&lt;P&gt;local_B = Local_matrix_allocate(n_bar); // Memory for submatrix B in each process&lt;/P&gt;&lt;P&gt;Order(local_B) = n_bar;&lt;/P&gt;&lt;P&gt;Generate_matrix("\\nGenerate B", local_B, &amp;amp;grid, n); // Only P(0) do this&lt;/P&gt;&lt;P&gt;Print_matrix("Matrix B =", local_B, &amp;amp;grid, n); // Only P(0) do this&lt;/P&gt;&lt;P&gt;Build_matrix_type(local_A); // Struct type for submatrix (MPI)&lt;/P&gt;&lt;P&gt;temp_mat = Local_matrix_allocate(n_bar); // Memory for Temp matrix&lt;/P&gt;&lt;P&gt;local_C = Local_matrix_allocate(n_bar); // Memory for result matrix C&lt;/P&gt;&lt;P&gt;Order(local_C) = n_bar; // Size of C&lt;/P&gt;&lt;P&gt;begin_time = MPI_Wtime();&lt;/P&gt;&lt;P&gt;Fox(n, &amp;amp;grid, local_A, local_B, local_C); // Block-algoritm of FOX&lt;/P&gt;&lt;P&gt;end_time = MPI_Wtime();&lt;/P&gt;&lt;P&gt;Print_matrix("\\nThe product is:", local_C, &amp;amp;grid, n);&lt;/P&gt;&lt;P&gt;interval_p = end_time - begin_time;&lt;/P&gt;&lt;P&gt;if (my_rank == 0) {&lt;/P&gt;&lt;P&gt;/* Sequential matrix multiplication */&lt;/P&gt;&lt;P&gt;interval_s = Sequential_time(n);&lt;/P&gt;&lt;P&gt;/* Speed-up */&lt;/P&gt;&lt;P&gt;printf("\\nTp = %.10f", interval_p);&lt;/P&gt;&lt;P&gt;printf("\\nTs = %.10f", interval_s);&lt;/P&gt;&lt;P&gt;printf("\\nS = %.10f\\n\\n", interval_s/interval_p);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;Free_local_matrix(&amp;amp;local_A);&lt;/P&gt;&lt;P&gt;Free_local_matrix(&amp;amp;local_B);&lt;/P&gt;&lt;P&gt;Free_local_matrix(&amp;amp;local_C);&lt;/P&gt;&lt;P&gt;return MPI_Finalize();&lt;/P&gt;&lt;P&gt;} /* main */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Setup_grid(&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid /* out */) {&lt;/P&gt;&lt;P&gt;int old_rank;&lt;/P&gt;&lt;P&gt;int dimensions[2];&lt;/P&gt;&lt;P&gt;int wrap_around[2];&lt;/P&gt;&lt;P&gt;int coordinates[2];&lt;/P&gt;&lt;P&gt;int free_coords[2];&lt;/P&gt;&lt;P&gt;/* Set up Global Grid Information */&lt;/P&gt;&lt;P&gt;MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;(grid-&amp;gt;p));&lt;/P&gt;&lt;P&gt;MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;old_rank);&lt;/P&gt;&lt;P&gt;/* We assume p is a perfect square */&lt;/P&gt;&lt;P&gt;grid-&amp;gt;q = (int) sqrt((double) grid-&amp;gt;p);&lt;/P&gt;&lt;P&gt;dimensions[0] = dimensions[1] = grid-&amp;gt;q;&lt;/P&gt;&lt;P&gt;/* We want a circular shift in second dimension. */&lt;/P&gt;&lt;P&gt;/* Don't care about first */&lt;/P&gt;&lt;P&gt;wrap_around[0] = wrap_around[1] = 1;&lt;/P&gt;&lt;P&gt;MPI_Cart_create(MPI_COMM_WORLD, 2, dimensions, wrap_around, 1, &amp;amp;(grid-&amp;gt;comm));&lt;/P&gt;&lt;P&gt;MPI_Comm_rank(grid-&amp;gt;comm, &amp;amp;(grid-&amp;gt;my_rank));&lt;/P&gt;&lt;P&gt;MPI_Cart_coords(grid-&amp;gt;comm, grid-&amp;gt;my_rank, 2, coordinates);&lt;/P&gt;&lt;P&gt;grid-&amp;gt;my_row = coordinates[0];&lt;/P&gt;&lt;P&gt;grid-&amp;gt;my_col = coordinates[1];&lt;/P&gt;&lt;P&gt;/* Set up row communicators */&lt;/P&gt;&lt;P&gt;free_coords[0] = 0;&lt;/P&gt;&lt;P&gt;free_coords[1] = 1;&lt;/P&gt;&lt;P&gt;MPI_Cart_sub(grid-&amp;gt;comm, free_coords, &amp;amp;(grid-&amp;gt;row_comm));&lt;/P&gt;&lt;P&gt;/* Set up column communicators */&lt;/P&gt;&lt;P&gt;free_coords[0] = 1;&lt;/P&gt;&lt;P&gt;free_coords[1] = 0;&lt;/P&gt;&lt;P&gt;MPI_Cart_sub(grid-&amp;gt;comm, free_coords, &amp;amp;(grid-&amp;gt;col_comm));&lt;/P&gt;&lt;P&gt;} /* Setup_grid */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Fox(&lt;/P&gt;&lt;P&gt;int n /* in */,&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_B /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_C /* out */) {&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* temp_A; /* Storage for the sub- */&lt;/P&gt;&lt;P&gt;/* matrix of A used during */&lt;/P&gt;&lt;P&gt;/* the current stage */&lt;/P&gt;&lt;P&gt;int stage;&lt;/P&gt;&lt;P&gt;int bcast_root;&lt;/P&gt;&lt;P&gt;int n_bar; /* n/sqrt(p) */&lt;/P&gt;&lt;P&gt;int source;&lt;/P&gt;&lt;P&gt;int dest;&lt;/P&gt;&lt;P&gt;MPI_Status status;&lt;/P&gt;&lt;P&gt;n_bar = n/grid-&amp;gt;q;&lt;/P&gt;&lt;P&gt;Set_to_zero(local_C);&lt;/P&gt;&lt;P&gt;/* Calculate addresses for circular shift of B */&lt;/P&gt;&lt;P&gt;source = (grid-&amp;gt;my_row + 1) % grid-&amp;gt;q; // (l + 1) mod q&lt;/P&gt;&lt;P&gt;dest = (grid-&amp;gt;my_row + grid-&amp;gt;q - 1) % grid-&amp;gt;q; // (l + q - 1) mod q&lt;/P&gt;&lt;P&gt;/* Set aside storage for the broadcast block of A */&lt;/P&gt;&lt;P&gt;temp_A = Local_matrix_allocate(n_bar);&lt;/P&gt;&lt;P&gt;for (stage = 0; stage &amp;lt; grid-&amp;gt;q; stage++) {&lt;/P&gt;&lt;P&gt;bcast_root = (grid-&amp;gt;my_row + stage) % grid-&amp;gt;q; // (l + stage) mod q --&amp;gt; (n)&lt;/P&gt;&lt;P&gt;if (bcast_root == grid-&amp;gt;my_col) { // if (n == k)&lt;/P&gt;&lt;P&gt;MPI_Bcast(local_A, 1, local_matrix_mpi_t, // Broadcasting of A[l,k] (sub-block)&lt;/P&gt;&lt;P&gt;bcast_root, grid-&amp;gt;row_comm);&lt;/P&gt;&lt;P&gt;Local_matrix_multiply(local_A, local_B, // C[l,k] += (A[l,n] * B[n,k])&lt;/P&gt;&lt;P&gt;local_C);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;else {&lt;/P&gt;&lt;P&gt;MPI_Bcast(temp_A, 1, local_matrix_mpi_t,&lt;/P&gt;&lt;P&gt;bcast_root, grid-&amp;gt;row_comm);&lt;/P&gt;&lt;P&gt;Local_matrix_multiply(temp_A, local_B,&lt;/P&gt;&lt;P&gt;local_C);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;MPI_Sendrecv_replace(local_B, 1, local_matrix_mpi_t, //Sends and receives using a single buffer&lt;/P&gt;&lt;P&gt;dest, 0/* sendtag*/, source, 0/*recvtag*/, grid-&amp;gt;col_comm, &amp;amp;status);&lt;/P&gt;&lt;P&gt;} /* for */&lt;/P&gt;&lt;P&gt;} /* Fox */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* Local_matrix_allocate(int local_order) {&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* temp;&lt;/P&gt;&lt;P&gt;temp = (LOCAL_MATRIX_T*) malloc(sizeof(LOCAL_MATRIX_T));&lt;/P&gt;&lt;P&gt;return temp;&lt;/P&gt;&lt;P&gt;} /* Local_matrix_allocate */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Free_local_matrix(&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T** local_A_ptr /* in/out */) {&lt;/P&gt;&lt;P&gt;free(*local_A_ptr);&lt;/P&gt;&lt;P&gt;} /* Free_local_matrix */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;/* Read and distribute matrix:&lt;/P&gt;&lt;P&gt;* foreach global row of the matrix,&lt;/P&gt;&lt;P&gt;* foreach grid column&lt;/P&gt;&lt;P&gt;* read a block of n_bar floats on process 0&lt;/P&gt;&lt;P&gt;* and send them to the appropriate process.&lt;/P&gt;&lt;P&gt;*/&lt;/P&gt;&lt;P&gt;void Generate_matrix(&lt;/P&gt;&lt;P&gt;char* title /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* out */,&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid /* in */,&lt;/P&gt;&lt;P&gt;int n /* in */) {&lt;/P&gt;&lt;P&gt;int mat_row, mat_col;&lt;/P&gt;&lt;P&gt;int grid_row, grid_col;&lt;/P&gt;&lt;P&gt;int dest;&lt;/P&gt;&lt;P&gt;int coords[2];&lt;/P&gt;&lt;P&gt;float* temp;&lt;/P&gt;&lt;P&gt;MPI_Status status;&lt;/P&gt;&lt;P&gt;if (grid-&amp;gt;my_rank == 0) {&lt;/P&gt;&lt;P&gt;//printf("%d\\n", grid-&amp;gt;my_rank);&lt;/P&gt;&lt;P&gt;temp = (float*) malloc(Order(local_A)*sizeof(float));&lt;/P&gt;&lt;P&gt;printf("%s\\n", title);&lt;/P&gt;&lt;P&gt;fflush(stdout);&lt;/P&gt;&lt;P&gt;for (mat_row = 0; mat_row &amp;lt; n; mat_row++) {&lt;/P&gt;&lt;P&gt;grid_row = mat_row/Order(local_A);&lt;/P&gt;&lt;P&gt;coords[0] = grid_row;&lt;/P&gt;&lt;P&gt;for (grid_col = 0; grid_col &amp;lt; grid-&amp;gt;q; grid_col++) {&lt;/P&gt;&lt;P&gt;coords[1] = grid_col;&lt;/P&gt;&lt;P&gt;MPI_Cart_rank(grid-&amp;gt;comm, coords, &amp;amp;dest);&lt;/P&gt;&lt;P&gt;if (dest == 0) {&lt;/P&gt;&lt;P&gt;for (mat_col = 0; mat_col &amp;lt; Order(local_A); mat_col++)&lt;/P&gt;&lt;P&gt;//scanf("%f", (local_A-&amp;gt;entries)+mat_row*Order(local_A)+mat_col);&lt;/P&gt;&lt;P&gt;*((local_A-&amp;gt;entries)+mat_row*Order(local_A)+mat_col) = RandVal;&lt;/P&gt;&lt;P&gt;} else {&lt;/P&gt;&lt;P&gt;for(mat_col = 0; mat_col &amp;lt; Order(local_A); mat_col++)&lt;/P&gt;&lt;P&gt;//scanf("%f", temp + mat_col);&lt;/P&gt;&lt;P&gt;*(temp + mat_col) = RandVal;&lt;/P&gt;&lt;P&gt;MPI_Send(temp, Order(local_A), MPI_FLOAT, dest, 0,&lt;/P&gt;&lt;P&gt;grid-&amp;gt;comm);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;free(temp);&lt;/P&gt;&lt;P&gt;} else {&lt;/P&gt;&lt;P&gt;for (mat_row = 0; mat_row &amp;lt; Order(local_A); mat_row++)&lt;/P&gt;&lt;P&gt;MPI_Recv(&amp;amp;Entry(local_A, mat_row, 0), Order(local_A),&lt;/P&gt;&lt;P&gt;MPI_FLOAT, 0, 0, grid-&amp;gt;comm, &amp;amp;status);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;} /* Read_matrix */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Print_matrix(&lt;/P&gt;&lt;P&gt;char* title /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* out */,&lt;/P&gt;&lt;P&gt;GRID_INFO_T* grid /* in */,&lt;/P&gt;&lt;P&gt;int n /* in */) {&lt;/P&gt;&lt;P&gt;int mat_row, mat_col;&lt;/P&gt;&lt;P&gt;int grid_row, grid_col;&lt;/P&gt;&lt;P&gt;int source;&lt;/P&gt;&lt;P&gt;int coords[2];&lt;/P&gt;&lt;P&gt;float* temp;&lt;/P&gt;&lt;P&gt;MPI_Status status;&lt;/P&gt;&lt;P&gt;if (grid-&amp;gt;my_rank == 0) {&lt;/P&gt;&lt;P&gt;temp = (float*) malloc(Order(local_A)*sizeof(float));&lt;/P&gt;&lt;P&gt;printf("%s\\n", title);&lt;/P&gt;&lt;P&gt;for (mat_row = 0; mat_row &amp;lt; n; mat_row++) {&lt;/P&gt;&lt;P&gt;grid_row = mat_row/Order(local_A);&lt;/P&gt;&lt;P&gt;coords[0] = grid_row;&lt;/P&gt;&lt;P&gt;for (grid_col = 0; grid_col &amp;lt; grid-&amp;gt;q; grid_col++) {&lt;/P&gt;&lt;P&gt;coords[1] = grid_col;&lt;/P&gt;&lt;P&gt;MPI_Cart_rank(grid-&amp;gt;comm, coords, &amp;amp;source);&lt;/P&gt;&lt;P&gt;if (source == 0) {&lt;/P&gt;&lt;P&gt;for(mat_col = 0; mat_col &amp;lt; Order(local_A); mat_col++)&lt;/P&gt;&lt;P&gt;printf("%6.1f ", Entry(local_A, mat_row, mat_col));&lt;/P&gt;&lt;P&gt;} else {&lt;/P&gt;&lt;P&gt;MPI_Recv(temp, Order(local_A), MPI_FLOAT, source, 0,&lt;/P&gt;&lt;P&gt;grid-&amp;gt;comm, &amp;amp;status);&lt;/P&gt;&lt;P&gt;for(mat_col = 0; mat_col &amp;lt; Order(local_A); mat_col++)&lt;/P&gt;&lt;P&gt;printf("%6.1f ", temp[mat_col]);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;printf("\\n");&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;free(temp);&lt;/P&gt;&lt;P&gt;} else {&lt;/P&gt;&lt;P&gt;for (mat_row = 0; mat_row &amp;lt; Order(local_A); mat_row++)&lt;/P&gt;&lt;P&gt;MPI_Send(&amp;amp;Entry(local_A, mat_row, 0), Order(local_A),&lt;/P&gt;&lt;P&gt;MPI_FLOAT, 0, 0, grid-&amp;gt;comm);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;} /* Print_matrix */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Set_to_zero(&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* out */) {&lt;/P&gt;&lt;P&gt;int i, j;&lt;/P&gt;&lt;P&gt;for (i = 0; i &amp;lt; Order(local_A); i++)&lt;/P&gt;&lt;P&gt;for (j = 0; j &amp;lt; Order(local_A); j++)&lt;/P&gt;&lt;P&gt;Entry(local_A,i,j) = 0.0;&lt;/P&gt;&lt;P&gt;} /* Set_to_zero */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Build_matrix_type(&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* in */) {&lt;/P&gt;&lt;P&gt;MPI_Datatype temp_mpi_t;&lt;/P&gt;&lt;P&gt;int block_lengths[2];&lt;/P&gt;&lt;P&gt;MPI_Aint displacements[2];&lt;/P&gt;&lt;P&gt;MPI_Datatype typelist[2];&lt;/P&gt;&lt;P&gt;MPI_Aint start_address;&lt;/P&gt;&lt;P&gt;MPI_Aint address;&lt;/P&gt;&lt;P&gt;MPI_Type_contiguous(Order(local_A)*Order(local_A),&lt;/P&gt;&lt;P&gt;MPI_FLOAT, &amp;amp;temp_mpi_t); //array[0..n-1,0..n-1] of float&lt;/P&gt;&lt;P&gt;block_lengths[0] = block_lengths[1] = 1;&lt;/P&gt;&lt;P&gt;typelist[0] = MPI_INT; //2 elements: 1) int, 2) array[...] of float&lt;/P&gt;&lt;P&gt;typelist[1] = temp_mpi_t;&lt;/P&gt;&lt;P&gt;MPI_Address(local_A, &amp;amp;start_address); //adress of submatrix - start&lt;/P&gt;&lt;P&gt;MPI_Address(&amp;amp;(local_A-&amp;gt;n_bar), &amp;amp;address); //adress of Size of submatrix&lt;/P&gt;&lt;P&gt;displacements[0] = address - start_address; //between n_bar and beginning (sometimes &amp;lt;&amp;gt;0 )&lt;/P&gt;&lt;P&gt;MPI_Address(local_A-&amp;gt;entries, &amp;amp;address); //adress of entries&lt;/P&gt;&lt;P&gt;displacements[1] = address - start_address; //between entries and beginning&lt;/P&gt;&lt;P&gt;MPI_Type_struct(2, block_lengths, displacements, //new struct type&lt;/P&gt;&lt;P&gt;typelist, &amp;amp;local_matrix_mpi_t);&lt;/P&gt;&lt;P&gt;MPI_Type_commit(&amp;amp;local_matrix_mpi_t); //return type?&lt;/P&gt;&lt;P&gt;} /* Build_matrix_type */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;void Local_matrix_multiply(&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_A /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_B /* in */,&lt;/P&gt;&lt;P&gt;LOCAL_MATRIX_T* local_C /* out */) {&lt;/P&gt;&lt;P&gt;int i, j, k;&lt;/P&gt;&lt;P&gt;for (i = 0; i &amp;lt; Order(local_A); i++)&lt;/P&gt;&lt;P&gt;for (j = 0; j &amp;lt; Order(local_A); j++)&lt;/P&gt;&lt;P&gt;for (k = 0; k &amp;lt; Order(local_B); k++)&lt;/P&gt;&lt;P&gt;Entry(local_C,i,j) += Entry(local_A,i,k)*Entry(local_B,k,j);&lt;/P&gt;&lt;P&gt;} /* Local_matrix_multiply */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;/*********************************************************/&lt;/P&gt;&lt;P&gt;double Sequential_time(int n) {&lt;/P&gt;&lt;P&gt;int i,j,k;&lt;/P&gt;&lt;P&gt;double begin_time, end_time;&lt;/P&gt;&lt;P&gt;float *A = (float *) malloc(n*n * sizeof(float));&lt;/P&gt;&lt;P&gt;float* B = (float *) malloc(n*n * sizeof(float));&lt;/P&gt;&lt;P&gt;float* C = (float *) malloc(n*n * sizeof(float));&lt;/P&gt;&lt;P&gt;for (i=0; i&lt;N&gt;&lt;/N&gt;&lt;/P&gt;&lt;P&gt;A&lt;I&gt; = RandVal; B&lt;I&gt; = RandVal; C&lt;I&gt; = 0.0;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;begin_time = MPI_Wtime();&lt;/P&gt;&lt;P&gt;for (i = 0; i &amp;lt; n; i++) {&lt;/P&gt;&lt;P&gt;for (j = 0; j &amp;lt; n; j++) {&lt;/P&gt;&lt;P&gt;for (k = 0; k &amp;lt; n; k++) {&lt;/P&gt;&lt;P&gt;C[i*n+j] += A[i*n+k]*B[k*n+j];&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;end_time = MPI_Wtime();&lt;/P&gt;&lt;P&gt;free(A); free(B); free(C);&lt;/P&gt;&lt;P&gt;return end_time - begin_time;&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;</description>
      <pubDate>Wed, 23 Mar 2011 18:48:24 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-MPI-Library/opemnp-mpi-code-for-Matrix-multiplication/m-p/776925#M295</guid>
      <dc:creator>dusear4la</dc:creator>
      <dc:date>2011-03-23T18:48:24Z</dc:date>
    </item>
    <item>
      <title>opemnp/mpi code for Matrix multiplication</title>
      <link>https://community.intel.com/t5/Intel-MPI-Library/opemnp-mpi-code-for-Matrix-multiplication/m-p/776926#M296</link>
      <description>You'd better ask in this &lt;A href="http://software.intel.com/en-us/forums/intel-parallel-studio/"&gt;forum&lt;/A&gt;.&lt;BR /&gt;I'm not sure that people knowing openMP read this forum.&lt;BR /&gt;&lt;BR /&gt;Regards!&lt;BR /&gt; Dmitry&lt;BR /&gt;</description>
      <pubDate>Thu, 24 Mar 2011 09:09:14 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-MPI-Library/opemnp-mpi-code-for-Matrix-multiplication/m-p/776926#M296</guid>
      <dc:creator>Dmitry_K_Intel2</dc:creator>
      <dc:date>2011-03-24T09:09:14Z</dc:date>
    </item>
    <item>
      <title>opemnp/mpi code for Matrix multiplication</title>
      <link>https://community.intel.com/t5/Intel-MPI-Library/opemnp-mpi-code-for-Matrix-multiplication/m-p/776927#M297</link>
      <description>Parallel Studio might be useful for optimizing a single multi-threaded rank for a Windows target. Basically, you would like to thread the outermost loop. You might get a better combination of vector inner loop and parallel outer loop performance by borrowing some ideas from public sources, particularly if this is a class exercise. If not, you would likely get ahead faster by using one of the pre-optimized versions (MKL is already included with Intel compilers).</description>
      <pubDate>Thu, 24 Mar 2011 19:46:15 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-MPI-Library/opemnp-mpi-code-for-Matrix-multiplication/m-p/776927#M297</guid>
      <dc:creator>TimP</dc:creator>
      <dc:date>2011-03-24T19:46:15Z</dc:date>
    </item>
  </channel>
</rss>

