|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Changes to this example
|
|
Packit Service |
c5cf8c |
* (C) 2001 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* This example is taken from MPI-The complete reference, Vol 1,
|
|
Packit Service |
c5cf8c |
* pages 222-224.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Lines after the "--CUT HERE--" were added to make this into a complete
|
|
Packit Service |
c5cf8c |
* test program.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Specify the maximum number of errors to report. */
|
|
Packit Service |
c5cf8c |
#define MAX_ERRORS 10
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "mpi.h"
|
|
Packit Service |
c5cf8c |
#include "mpitest.h"
|
|
Packit Service |
c5cf8c |
#include <stdio.h>
|
|
Packit Service |
c5cf8c |
#include <stdlib.h>
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MAX_SIZE 64
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPI_Datatype transpose_type(int M, int m, int n, MPI_Datatype type);
|
|
Packit Service |
c5cf8c |
MPI_Datatype submatrix_type(int N, int m, int n, MPI_Datatype type);
|
|
Packit Service |
c5cf8c |
void Transpose(float *localA, float *localB, int M, int N, MPI_Comm comm);
|
|
Packit Service |
c5cf8c |
void Transpose(float *localA, float *localB, int M, int N, MPI_Comm comm)
|
|
Packit Service |
c5cf8c |
/* transpose MxN matrix A that is block distributed (1-D) on
|
|
Packit Service |
c5cf8c |
processes of comm onto block distributed matrix B */
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int i, j, extent, myrank, p, n[2], m[2];
|
|
Packit Service |
c5cf8c |
int lasti, lastj;
|
|
Packit Service |
c5cf8c |
int *sendcounts, *recvcounts;
|
|
Packit Service |
c5cf8c |
int *sdispls, *rdispls;
|
|
Packit Service |
c5cf8c |
MPI_Datatype xtype[2][2], stype[2][2], *sendtypes, *recvtypes;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MTestPrintfMsg(2, "M = %d, N = %d\n", M, N);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* compute parameters */
|
|
Packit Service |
c5cf8c |
MPI_Comm_size(comm, &p);
|
|
Packit Service |
c5cf8c |
MPI_Comm_rank(comm, &myrank);
|
|
Packit Service |
c5cf8c |
extent = sizeof(float);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* allocate arrays */
|
|
Packit Service |
c5cf8c |
sendcounts = (int *) malloc(p * sizeof(int));
|
|
Packit Service |
c5cf8c |
recvcounts = (int *) malloc(p * sizeof(int));
|
|
Packit Service |
c5cf8c |
sdispls = (int *) malloc(p * sizeof(int));
|
|
Packit Service |
c5cf8c |
rdispls = (int *) malloc(p * sizeof(int));
|
|
Packit Service |
c5cf8c |
sendtypes = (MPI_Datatype *) malloc(p * sizeof(MPI_Datatype));
|
|
Packit Service |
c5cf8c |
recvtypes = (MPI_Datatype *) malloc(p * sizeof(MPI_Datatype));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* compute block sizes */
|
|
Packit Service |
c5cf8c |
m[0] = M / p;
|
|
Packit Service |
c5cf8c |
m[1] = M - (p - 1) * (M / p);
|
|
Packit Service |
c5cf8c |
n[0] = N / p;
|
|
Packit Service |
c5cf8c |
n[1] = N - (p - 1) * (N / p);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* compute types */
|
|
Packit Service |
c5cf8c |
for (i = 0; i <= 1; i++)
|
|
Packit Service |
c5cf8c |
for (j = 0; j <= 1; j++) {
|
|
Packit Service |
c5cf8c |
xtype[i][j] = transpose_type(N, m[i], n[j], MPI_FLOAT);
|
|
Packit Service |
c5cf8c |
stype[i][j] = submatrix_type(M, m[i], n[j], MPI_FLOAT);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* prepare collective operation arguments */
|
|
Packit Service |
c5cf8c |
lasti = myrank == p - 1;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < p; j++) {
|
|
Packit Service |
c5cf8c |
lastj = j == p - 1;
|
|
Packit Service |
c5cf8c |
sendcounts[j] = 1;
|
|
Packit Service |
c5cf8c |
sdispls[j] = j * n[0] * extent;
|
|
Packit Service |
c5cf8c |
sendtypes[j] = xtype[lasti][lastj];
|
|
Packit Service |
c5cf8c |
recvcounts[j] = 1;
|
|
Packit Service |
c5cf8c |
rdispls[j] = j * m[0] * extent;
|
|
Packit Service |
c5cf8c |
recvtypes[j] = stype[lastj][lasti];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* communicate */
|
|
Packit Service |
c5cf8c |
MTestPrintfMsg(2, "Begin Alltoallw...\n");
|
|
Packit Service |
c5cf8c |
/* -- Note that the book incorrectly uses &localA and &localB
|
|
Packit Service |
c5cf8c |
* as arguments to MPI_Alltoallw */
|
|
Packit Service |
c5cf8c |
MPI_Alltoallw(localA, sendcounts, sdispls, sendtypes,
|
|
Packit Service |
c5cf8c |
localB, recvcounts, rdispls, recvtypes, comm);
|
|
Packit Service |
c5cf8c |
MTestPrintfMsg(2, "Done with Alltoallw\n");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Free buffers */
|
|
Packit Service |
c5cf8c |
free(sendcounts);
|
|
Packit Service |
c5cf8c |
free(recvcounts);
|
|
Packit Service |
c5cf8c |
free(sdispls);
|
|
Packit Service |
c5cf8c |
free(rdispls);
|
|
Packit Service |
c5cf8c |
free(sendtypes);
|
|
Packit Service |
c5cf8c |
free(recvtypes);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Free datatypes */
|
|
Packit Service |
c5cf8c |
for (i = 0; i <= 1; i++)
|
|
Packit Service |
c5cf8c |
for (j = 0; j <= 1; j++) {
|
|
Packit Service |
c5cf8c |
MPI_Type_free(&xtype[i][j]);
|
|
Packit Service |
c5cf8c |
MPI_Type_free(&stype[i][j]);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Define an n x m submatrix in a n x M local matrix (this is the
|
|
Packit Service |
c5cf8c |
destination in the transpose matrix */
|
|
Packit Service |
c5cf8c |
MPI_Datatype submatrix_type(int M, int m, int n, MPI_Datatype type)
|
|
Packit Service |
c5cf8c |
/* computes a datatype for an mxn submatrix within an MxN matrix
|
|
Packit Service |
c5cf8c |
with entries of type type */
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
/* MPI_Datatype subrow; */
|
|
Packit Service |
c5cf8c |
MPI_Datatype submatrix;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* The book, MPI: The Complete Reference, has the wrong type constructor
|
|
Packit Service |
c5cf8c |
* here. Since the stride in the vector type is relative to the input
|
|
Packit Service |
c5cf8c |
* type, the stride in the book's code is n times as long as is intended.
|
|
Packit Service |
c5cf8c |
* Since n may not exactly divide N, it is better to simply use the
|
|
Packit Service |
c5cf8c |
* blocklength argument in Type_vector */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* MPI_Type_contiguous(n, type, &subrow);
|
|
Packit Service |
c5cf8c |
* MPI_Type_vector(m, 1, N, subrow, &submatrix);
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
MPI_Type_vector(n, m, M, type, &submatrix);
|
|
Packit Service |
c5cf8c |
MPI_Type_commit(&submatrix);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Add a consistency test: the size of submatrix should be
|
|
Packit Service |
c5cf8c |
* n * m * sizeof(type) and the extent should be ((n-1)*M+m) * sizeof(type) */
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int tsize;
|
|
Packit Service |
c5cf8c |
MPI_Aint textent, lb;
|
|
Packit Service |
c5cf8c |
MPI_Type_size(type, &tsize);
|
|
Packit Service |
c5cf8c |
MPI_Type_get_extent(submatrix, &lb, &textent);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (textent != tsize * (M * (n - 1) + m)) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Submatrix extent is %ld, expected %ld (%d,%d,%d)\n",
|
|
Packit Service |
c5cf8c |
(long) textent, (long) (tsize * (M * (n - 1) + m)), M, n, m);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return (submatrix);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Extract an m x n submatrix within an m x N matrix and transpose it.
|
|
Packit Service |
c5cf8c |
Assume storage by rows; the defined datatype accesses by columns */
|
|
Packit Service |
c5cf8c |
MPI_Datatype transpose_type(int N, int m, int n, MPI_Datatype type)
|
|
Packit Service |
c5cf8c |
/* computes a datatype for the transpose of an mxn matrix
|
|
Packit Service |
c5cf8c |
with entries of type type */
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPI_Datatype subrow, subrow1, submatrix;
|
|
Packit Service |
c5cf8c |
MPI_Aint lb, extent;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPI_Type_vector(m, 1, N, type, &subrow);
|
|
Packit Service |
c5cf8c |
MPI_Type_get_extent(type, &lb, &extent);
|
|
Packit Service |
c5cf8c |
MPI_Type_create_resized(subrow, 0, extent, &subrow1);
|
|
Packit Service |
c5cf8c |
MPI_Type_contiguous(n, subrow1, &submatrix);
|
|
Packit Service |
c5cf8c |
MPI_Type_commit(&submatrix);
|
|
Packit Service |
c5cf8c |
MPI_Type_free(&subrow);
|
|
Packit Service |
c5cf8c |
MPI_Type_free(&subrow1);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Add a consistency test: the size of submatrix should be
|
|
Packit Service |
c5cf8c |
* n * m * sizeof(type) and the extent should be ((m-1)*N+n) * sizeof(type) */
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int tsize;
|
|
Packit Service |
c5cf8c |
MPI_Aint textent, llb;
|
|
Packit Service |
c5cf8c |
MPI_Type_size(type, &tsize);
|
|
Packit Service |
c5cf8c |
MPI_Type_get_true_extent(submatrix, &llb, &textent);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (textent != tsize * (N * (m - 1) + n)) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Transpose Submatrix extent is %ld, expected %ld (%d,%d,%d)\n",
|
|
Packit Service |
c5cf8c |
(long) textent, (long) (tsize * (N * (m - 1) + n)), N, n, m);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return (submatrix);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* -- CUT HERE -- */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int main(int argc, char *argv[])
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int gM, gN, lm, lmlast, ln, lnlast, i, j, errs = 0;
|
|
Packit Service |
c5cf8c |
int size, rank;
|
|
Packit Service |
c5cf8c |
float *localA, *localB;
|
|
Packit Service |
c5cf8c |
MPI_Comm comm;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MTest_Init(&argc, &argv);
|
|
Packit Service |
c5cf8c |
comm = MPI_COMM_WORLD;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPI_Comm_size(comm, &size);
|
|
Packit Service |
c5cf8c |
MPI_Comm_rank(comm, &rank;;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
gM = 20;
|
|
Packit Service |
c5cf8c |
gN = 30;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Each block is lm x ln in size, except for the last process,
|
|
Packit Service |
c5cf8c |
* which has lmlast x lnlast */
|
|
Packit Service |
c5cf8c |
lm = gM / size;
|
|
Packit Service |
c5cf8c |
lmlast = gM - (size - 1) * lm;
|
|
Packit Service |
c5cf8c |
ln = gN / size;
|
|
Packit Service |
c5cf8c |
lnlast = gN - (size - 1) * ln;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Create the local matrices.
|
|
Packit Service |
c5cf8c |
* Initialize the input matrix so that the entries are
|
|
Packit Service |
c5cf8c |
* consequtive integers, by row, starting at 0.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
if (rank == size - 1) {
|
|
Packit Service |
c5cf8c |
localA = (float *) malloc(gN * lmlast * sizeof(float));
|
|
Packit Service |
c5cf8c |
localB = (float *) malloc(gM * lnlast * sizeof(float));
|
|
Packit Service |
c5cf8c |
for (i = 0; i < lmlast; i++) {
|
|
Packit Service |
c5cf8c |
for (j = 0; j < gN; j++) {
|
|
Packit Service |
c5cf8c |
localA[i * gN + j] = (float) (i * gN + j + rank * gN * lm);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
localA = (float *) malloc(gN * lm * sizeof(float));
|
|
Packit Service |
c5cf8c |
localB = (float *) malloc(gM * ln * sizeof(float));
|
|
Packit Service |
c5cf8c |
for (i = 0; i < lm; i++) {
|
|
Packit Service |
c5cf8c |
for (j = 0; j < gN; j++) {
|
|
Packit Service |
c5cf8c |
localA[i * gN + j] = (float) (i * gN + j + rank * gN * lm);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MTestPrintfMsg(2, "Allocated local arrays\n");
|
|
Packit Service |
c5cf8c |
/* Transpose */
|
|
Packit Service |
c5cf8c |
Transpose(localA, localB, gM, gN, comm);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* check the transposed matrix
|
|
Packit Service |
c5cf8c |
* In the global matrix, the transpose has consequtive integers,
|
|
Packit Service |
c5cf8c |
* organized by columns.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
if (rank == size - 1) {
|
|
Packit Service |
c5cf8c |
for (i = 0; i < lnlast; i++) {
|
|
Packit Service |
c5cf8c |
for (j = 0; j < gM; j++) {
|
|
Packit Service |
c5cf8c |
int expected = i + gN * j + rank * ln;
|
|
Packit Service |
c5cf8c |
if ((int) localB[i * gM + j] != expected) {
|
|
Packit Service |
c5cf8c |
if (errs < MAX_ERRORS)
|
|
Packit Service |
c5cf8c |
printf("Found %d but expected %d\n", (int) localB[i * gM + j], expected);
|
|
Packit Service |
c5cf8c |
errs++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
for (i = 0; i < ln; i++) {
|
|
Packit Service |
c5cf8c |
for (j = 0; j < gM; j++) {
|
|
Packit Service |
c5cf8c |
int expected = i + gN * j + rank * ln;
|
|
Packit Service |
c5cf8c |
if ((int) localB[i * gM + j] != expected) {
|
|
Packit Service |
c5cf8c |
if (errs < MAX_ERRORS)
|
|
Packit Service |
c5cf8c |
printf("Found %d but expected %d\n", (int) localB[i * gM + j], expected);
|
|
Packit Service |
c5cf8c |
errs++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Free storage */
|
|
Packit Service |
c5cf8c |
free(localA);
|
|
Packit Service |
c5cf8c |
free(localB);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MTest_Finalize(errs);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return MTestReturnValue(errs);
|
|
Packit Service |
c5cf8c |
}
|