Bu Blogda Ara

7 Şubat 2010 Pazar

Process 0 starts off the ring pass. * Fixed erroneous calc of time_array_order in Initialize. * Changed number of message sizes to 2. *

/* comm_time.c
* Version 6: Process 0 starts off the ring pass.
* Fixed erroneous calc of time_array_order in Initialize.
* Changed number of message sizes to 2.
* Removed debug output from Print_results.
* Corrected calculation of source process rank.
* Try to check sends and receives using Cprintfs in loop.
* Relocate Cprintfs in loop.
* Time communication around a ring of processes.
* Guaranteed to have bugs.
*
* Input: None (see notes).
*
* Output: Average, minimum, and maximum time for messages
* of varying sizes to be forwarded around a ring of
* processes.
*
* Algorithm:
* 1. Allocate and initialize storage for messages
* and communication times
* 2. Compute ranks of neighbors in ring.
* 3. Foreach message size
* 3b. Foreach test
* 3a. Start clock
* 3c. Send message around loop
* 3d. Add elapsed time to running sum
* 3e. Update max/min elapsed time
* 4. Print times.
*
* Functions:
* Initialize: Allocate and initialize arrays
* Print_results: Send results to I/O process
* and print.
*
* Notes:
* 1. Due to difficulties some MPI implementations
* have with input, the number of tests, the max
* message size, the min message size, and the size
* increment are hardwired.
* 2. We assume that the size increment evenly divides
* the difference max_size - min_size
*
* See Chap 9, pp. 192 & ff and pp. 209 & ff in PPMPI.
*/
#include
#include "mpi.h"
#include "cio.h"

void Initialize(int max_size, int min_size, int size_incr,
int my_rank, float** x_ptr, double** times_ptr,
double** max_times_ptr, double** min_times_ptr,
int* order_ptr);

void Print_results(MPI_Comm io_comm, int my_rank,
int min_size, int max_size, int size_incr,
int time_array_order, int test_count,
double* times, double* max_times, double* min_times);

main(int argc, char* argv[]) {
int test_count = 2; /* Number of tests */
int max_size = 1000; /* Max msg. length */
int min_size = 0; /* Min msg. length */
int size_incr = 1000; /* Increment for */
/* msg. sizes */
float* x; /* Message buffer */
double* times; /* Elapsed times */
double* max_times; /* Max times */
double* min_times; /* Min times */
int time_array_order; /* Size of timing */
/* arrays. */
double start; /* Start time */
double elapsed; /* Elapsed time */
int i, test, size; /* Loop variables */
int p, my_rank, source, dest;
MPI_Comm io_comm;
MPI_Status status;

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &p);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_dup(MPI_COMM_WORLD, &io_comm);
Cache_io_rank(MPI_COMM_WORLD, io_comm);

Cprintf(io_comm,"","Before Initialize, p = %d, my_rank = %d",
p, my_rank);
Initialize(max_size, min_size, size_incr, my_rank,
&x, ×, &max_times, &min_times,
&time_array_order);

source = (my_rank - 1 + p) % p;
dest = (my_rank + 1) % p;

/* For each message size, find average circuit time */
/* Loop var size = message size */
/* Loop var i = index into arrays for timings */
for (size = min_size, i = 0; size <= max_size;
size = size + size_incr, i++) {
Cprintf(io_comm,"",
"Before if, my_rank = %d, source = %d, dest = %d",
my_rank, source, dest);
if (my_rank == 0) {
times[i] =0.0;
max_times[i] = 0.0;
min_times[i] = 1000000.0;
for (test = 0; test < test_count; test++) {
start = MPI_Wtime();
Cprintf(io_comm,"",
"Before send x[0] = %f, size = %d, dest = %d",
my_rank, x[0], size, dest);
MPI_Send(x, size, MPI_FLOAT, dest, 0,
MPI_COMM_WORLD);
MPI_Recv(x, size, MPI_FLOAT, source, 0,
MPI_COMM_WORLD, &status);
Cprintf(io_comm,"",
"After recv x[0] = %f, size = %d, source = %d",
my_rank, x[0], size, source);
elapsed = MPI_Wtime() - start;
times[i] = times[i] + elapsed;
if (elapsed > max_times[i])
max_times[i] = elapsed;
if (elapsed < min_times[i])
min_times[i] = elapsed;
}
} else { /* my_rank != 0 */
for (test = 0; test < test_count; test++) {
Cprintf(io_comm,"",
"Before recv x[0] = %f, size = %d, source = %d",
my_rank, x[0], size, source);
MPI_Recv(x, size, MPI_FLOAT, source, 0,
MPI_COMM_WORLD, &status);
MPI_Send(x, size, MPI_FLOAT, dest, 0,
MPI_COMM_WORLD);
Cprintf(io_comm,"",
"After send x[0] = %f, size = %d, dest = %d",
my_rank, x[0], size, dest);
}
}
} /* for size . . . */

Print_results(io_comm, my_rank, min_size, max_size,
size_incr, time_array_order, test_count, times,
max_times, min_times);

MPI_Finalize();
} /* main */

/********************************************************/
void Initialize(int max_size, int min_size, int size_incr,
int my_rank, float** x_ptr, double** times_ptr,
double** max_times_ptr, double** min_times_ptr,
int* order_ptr) {
int i;

*x_ptr = (float *) malloc(max_size*sizeof(float));

*order_ptr = (max_size - min_size)/size_incr + 1;
*times_ptr =
(double *) malloc((*order_ptr)*sizeof(double));
*max_times_ptr =
(double *) malloc((*order_ptr)*sizeof(double));
*min_times_ptr =
(double *) malloc((*order_ptr)*sizeof(double));

/* Initialize buffer -- why this? */
for (i = 0; i < max_size; i++)
(*x_ptr)[i] = (float) my_rank;
} /* Initialize */


/********************************************************/
/* Send results from process 0 in MPI_COMM_WORLD to */
/* I/O process in io_comm, which prints the results. */
void Print_results(MPI_Comm io_comm, int my_rank,
int min_size, int max_size, int size_incr,
int time_array_order, int test_count, double* times,
double* max_times, double* min_times) {
int i;
int size;
MPI_Status status;
int io_process;
int io_rank;

Get_io_rank(io_comm, &io_process);
MPI_Comm_rank(io_comm, &io_rank);

if (my_rank == 0) {
MPI_Send(times, time_array_order, MPI_DOUBLE,
io_rank, 0, io_comm);
MPI_Send(max_times, time_array_order, MPI_DOUBLE,
io_process, 0, io_comm);
MPI_Send(min_times, time_array_order, MPI_DOUBLE,
io_process, 0, io_comm);
}
if (io_rank == io_process) {
MPI_Recv(times, time_array_order, MPI_DOUBLE,
MPI_ANY_SOURCE, 0, io_comm, &status);
MPI_Recv(max_times, time_array_order, MPI_DOUBLE,
MPI_ANY_SOURCE, 0, io_comm, &status);
MPI_Recv(min_times, time_array_order, MPI_DOUBLE,
MPI_ANY_SOURCE, 0, io_comm, &status);

printf("Message size (floats): ");
for (size = min_size;
size <= max_size; size += size_incr)
printf("%10d ", size);
printf("\n");

printf("Avg circuit time (ms): ");
for (i = 0; i < time_array_order; i++)
printf("%10f ",1000.0*times[i]/test_count);
printf("\n");
printf("Max circuit time (ms): ");
for (i = 0; i < time_array_order; i++)
printf("%10f ",1000.0*max_times[i]);
printf("\n");
printf("Min circuit time (ms): ");
for (i = 0; i < time_array_order; i++)
printf("%10f ",1000.0*min_times[i]);
printf("\n\n");
fflush(stdout);
}
} /* Print_results */

Computes a parallel dot product. Uses MPI_Allreduce.

/* parallel_dot1.c -- Computes a parallel dot product. Uses MPI_Allreduce.
*
* Input:
* n: order of vectors
* x, y: the vectors
*
* Output:
* the dot product of x and y as computed by each process.
*
* Note: Arrays containing vectors are statically allocated. Assumes that
* n, the global order of the vectors, is evenly divisible by p, the
* number of processes.
*
* See Chap 5, pp. 76 & ff in PPMPI.
*/
#include
#include "mpi.h"

#define MAX_LOCAL_ORDER 100

main(int argc, char* argv[]) {
float local_x[MAX_LOCAL_ORDER];
float local_y[MAX_LOCAL_ORDER];
int n;
int n_bar; /* = n/p */
float dot;
int p;
int my_rank;

void Read_vector(char* prompt, float local_v[], int n_bar, int p,
int my_rank);
float Parallel_dot(float local_x[], float local_y[], int n_bar);
void Print_results(float dot, int my_rank, int p);

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &p);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

if (my_rank == 0) {
printf("Enter the order of the vectors\n");
scanf("%d", &n);
}
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
n_bar = n/p;

Read_vector("the first vector", local_x, n_bar, p, my_rank);
Read_vector("the second vector", local_y, n_bar, p, my_rank);

dot = Parallel_dot(local_x, local_y, n_bar);

Print_results(dot, my_rank, p);

MPI_Finalize();
} /* main */


/*****************************************************************/
void Read_vector(
char* prompt /* in */,
float local_v[] /* out */,
int n_bar /* in */,
int p /* in */,
int my_rank /* in */) {
int i, q;
float temp[MAX_LOCAL_ORDER];
MPI_Status status;

if (my_rank == 0) {
printf("Enter %s\n", prompt);
for (i = 0; i < n_bar; i++)
scanf("%f", &local_v[i]);
for (q = 1; q < p; q++) {
for (i = 0; i < n_bar; i++)
scanf("%f", &temp[i]);
MPI_Send(temp, n_bar, MPI_FLOAT, q, 0, MPI_COMM_WORLD);
}
} else {
MPI_Recv(local_v, n_bar, MPI_FLOAT, 0, 0, MPI_COMM_WORLD,
&status);
}
} /* Read_vector */


/*****************************************************************/
float Serial_dot(
float x[] /* in */,
float y[] /* in */,
int n /* in */) {

int i;
float sum = 0.0;

for (i = 0; i < n; i++)
sum = sum + x[i]*y[i];
return sum;
} /* Serial_dot */


/*****************************************************************/
float Parallel_dot(
float local_x[] /* in */,
float local_y[] /* in */,
int n_bar /* in */) {

float local_dot;
float dot = 0.0;
float Serial_dot(float x[], float y[], int m);

local_dot = Serial_dot(local_x, local_y, n_bar);
MPI_Allreduce(&local_dot, &dot, 1, MPI_FLOAT,
MPI_SUM, MPI_COMM_WORLD);
return dot;
} /* Parallel_dot */


/*****************************************************************/
void Print_results(
float dot /* in */,
int my_rank /* in */,
int p /* in */) {
int q;
float temp;
MPI_Status status;

if (my_rank == 0) {
printf("dot = \n");
printf("Process 0 > %f\n", dot);
for (q = 1; q < p; q++) {
MPI_Recv(&temp, 1, MPI_FLOAT, q, 0, MPI_COMM_WORLD,
&status);
printf("Process %d > %f\n", q, temp);
}
} else {
MPI_Send(&dot, 1, MPI_FLOAT, 0, 0, MPI_COMM_WORLD);
}

} /* Print_results */

pack a row of a sparse matrix and send from process 0 * to process 1. Process 1 allocates required storage after partially * unpacking.

/* sparse_row.c -- pack a row of a sparse matrix and send from process 0
* to process 1. Process 1 allocates required storage after partially
* unpacking.
*
* Input: none
* Output: the row received by process 1.
*
* Notes:
* 1. This program should only be run with 2 processes.
* 2. Only the row of the matrix is created on both processes.
*
* See Chap. 6, pp. 104 & ff in PPMPI
*/
#include
#include
#include "mpi.h"

#define HUGE 100

main(int argc, char* argv[]) {
int p;
int my_rank;
float* entries;
int* column_subscripts;
int nonzeroes;
int position;
int row_number;
char buffer[HUGE]; /* HUGE is a predefined constant */
MPI_Status status;
int i;

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &p);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

if (my_rank == 0) {
/* Get the number of nonzeros in the row. */
/* Allocate storage for the row. */
/* Initialize entries and column_subscripts */
nonzeroes = 10;
entries = (float*) malloc(nonzeroes*sizeof(float));
column_subscripts = (int*) malloc(nonzeroes*sizeof(int));
for (i = 0; i < nonzeroes; i++) {
entries[i] = (float) 2*i;
column_subscripts[i] = 3*i;
}

/* Now pack the data and send */
position = 0;
MPI_Pack(&nonzeroes, 1, MPI_INT, buffer, HUGE,
&position, MPI_COMM_WORLD);
MPI_Pack(&row_number, 1, MPI_INT, buffer, HUGE,
&position, MPI_COMM_WORLD);
MPI_Pack(entries, nonzeroes, MPI_FLOAT, buffer,
HUGE, &position, MPI_COMM_WORLD);
MPI_Pack(column_subscripts, nonzeroes, MPI_INT,
buffer, HUGE, &position, MPI_COMM_WORLD);
MPI_Send(buffer, position, MPI_PACKED, 1, 0,
MPI_COMM_WORLD);
} else { /* my_rank == 1 */
MPI_Recv(buffer, HUGE, MPI_PACKED, 0, 0,
MPI_COMM_WORLD, &status);
position = 0;
MPI_Unpack(buffer, HUGE, &position, &nonzeroes,
1, MPI_INT, MPI_COMM_WORLD);
MPI_Unpack(buffer, HUGE, &position, &row_number,
1, MPI_INT, MPI_COMM_WORLD);
/* Allocate storage for entries and column_subscripts */
entries = (float *) malloc(nonzeroes*sizeof(float));
column_subscripts = (int *) malloc(nonzeroes*sizeof(int));
MPI_Unpack(buffer,HUGE, &position, entries,
nonzeroes, MPI_FLOAT, MPI_COMM_WORLD);
MPI_Unpack(buffer, HUGE, &position, column_subscripts,
nonzeroes, MPI_INT, MPI_COMM_WORLD);
for (i = 0; i < nonzeroes; i++)
printf("%4.1f %2d\n", entries[i], column_subscripts[i]);
}

MPI_Finalize();
} /* main */

send the upper triangle of a matrix from process 0 * to process 1

/* send_triangle.c -- send the upper triangle of a matrix from process 0
* to process 1
*
* Input: None
* Output: The matrix received by process 1
*
* Note: This program should only be run with 2 processes.
*
* See Chap 6, p. 98, in PPMPI.
*/
#include
#include "mpi.h"

#define n 10

main(int argc, char* argv[]) {
int p;
int my_rank;
float A[n][n]; /* Complete Matrix */
float T[n][n]; /* Upper Triangle */
int displacements[n];
int block_lengths[n];
MPI_Datatype index_mpi_t;
int i, j;
MPI_Status status;

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &p);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

for (i = 0; i < n; i++) {
block_lengths[i] = n-i;
displacements[i] = (n+1)*i;
}
MPI_Type_indexed(n, block_lengths, displacements,
MPI_FLOAT, &index_mpi_t);
MPI_Type_commit(&index_mpi_t);

if (my_rank == 0) {
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
A[i][j] = (float) i + j;
MPI_Send(A, 1, index_mpi_t, 1, 0, MPI_COMM_WORLD);
} else {/* my_rank == 1 */
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
T[i][j] = 0.0;
MPI_Recv(T, 1, index_mpi_t, 0, 0, MPI_COMM_WORLD, &status);
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
printf("%4.1f ", T[i][j]);
printf("\n");
}
}

MPI_Finalize();
} /* main */

send third row of a matrix from process 0 to process 1

/* send_row.c -- send third row of a matrix from process 0 to process 1
*
* Input: none
* Output: the row received by process 1
*
* Note: Program should only be run with 2 processes
*
* See Chap 6, p. 96 in PPMPI
*/
#include
#include "mpi.h"

main(int argc, char* argv[]) {
int p;
int my_rank;
float A[10][10];
MPI_Status status;
int i, j;

MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

if (my_rank == 0) {
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
A[i][j] = (float) i;
MPI_Send(&(A[2][0]), 10, MPI_FLOAT, 1, 0,
MPI_COMM_WORLD);
} else { /* my_rank = 1 */
MPI_Recv(&(A[2][0]), 10, MPI_FLOAT, 0, 0,
MPI_COMM_WORLD, &status);
for (j = 0; j < 10; j++)
printf("%3.1f ", A[2][j]);
printf("\n");
}

MPI_Finalize();
} /* main */

send column 1 of a matrix on process 0 to row 1 * on process 1.

/* send_col_to_row.c -- send column 1 of a matrix on process 0 to row 1
* on process 1.
*
* Input: none
* Output: The row received by process 1.
*
* Note: This program should only be run with 2 processes
*
* See Chap 6., pp. 98 & ff in PPMPI
*/
#include
#include "mpi.h"

main(int argc, char* argv[]) {
int p;
int my_rank;
float A[10][10];
MPI_Status status;
MPI_Datatype column_mpi_t;
int i, j;

MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

MPI_Type_vector(10, 1, 10, MPI_FLOAT, &column_mpi_t);
MPI_Type_commit(&column_mpi_t);

if (my_rank == 0) {
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
A[i][j] = (float) i;
MPI_Send(&(A[0][0]), 1, column_mpi_t, 1, 0,
MPI_COMM_WORLD);
} else { /* my_rank = 1 */
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
A[i][j] = 0.0;
MPI_Recv(&(A[0][0]), 10, MPI_FLOAT, 0, 0,
MPI_COMM_WORLD, &status);
for (j = 0; j < 10; j++)
printf("%3.1f ", A[0][j]);
printf("\n");
}

MPI_Finalize();
} /* main */

send the third column of a matrix from process 0 to * process 1

/* send_col.c -- send the third column of a matrix from process 0 to
* process 1
*
* Input: None
* Output: The column received by process 1
*
* Note: This program should only be run with 2 processes
*
* See Chap 6., pp. 96 & ff in PPMPI
*/
#include
#include "mpi.h"

main(int argc, char* argv[]) {
int p;
int my_rank;
float A[10][10];
MPI_Status status;
MPI_Datatype column_mpi_t;
int i, j;

MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

MPI_Type_vector(10, 1, 10, MPI_FLOAT, &column_mpi_t);
MPI_Type_commit(&column_mpi_t);

if (my_rank == 0) {
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
A[i][j] = (float) j;
MPI_Send(&(A[0][2]), 1, column_mpi_t, 1, 0,
MPI_COMM_WORLD);
} else { /* my_rank = 1 */
MPI_Recv(&(A[0][2]), 1, column_mpi_t, 0, 0,
MPI_COMM_WORLD, &status);
for (i = 0; i < 10; i++)
printf("%3.1f ", A[i][2]);
printf("\n");
}

MPI_Finalize();
} /* main */