| [6e48678] | 1 | /**
|
|---|
| 2 | * This program illustrates MPI_Scan.
|
|---|
| 3 | * online source: http://mpi.deino.net/mpi_functions/MPI_Scan.html
|
|---|
| 4 | */
|
|---|
| 5 | #include "mpi.h"
|
|---|
| 6 | #include <stdio.h>
|
|---|
| 7 |
|
|---|
| 8 | void addem ( int *, int *, int *, MPI_Datatype * );
|
|---|
| 9 | void assoc ( int *, int *, int *, MPI_Datatype * );
|
|---|
| 10 |
|
|---|
| 11 | void addem( int *invec, int *inoutvec, int *len, MPI_Datatype *dtype)
|
|---|
| 12 | {
|
|---|
| 13 | int i;
|
|---|
| 14 | for ( i=0; i<*len; i++ )
|
|---|
| 15 | inoutvec[i] += invec[i];
|
|---|
| 16 | }
|
|---|
| 17 | #define BAD_ANSWER 100000
|
|---|
| 18 | /*
|
|---|
| 19 | The operation is inoutvec[i] = invec[i] op inoutvec[i]
|
|---|
| 20 | (see 4.9.4). The order is important.
|
|---|
| 21 | Note that the computation is in process rank (in the communicator) order, independant of the root.
|
|---|
| 22 | */
|
|---|
| 23 | void assoc( int *invec, int *inoutvec, int *len, MPI_Datatype *dtype)
|
|---|
| 24 | {
|
|---|
| 25 | int i;
|
|---|
| 26 | for ( i=0; i<*len; i++ ) {
|
|---|
| 27 | if (inoutvec[i] <= invec[i] ) {
|
|---|
| 28 | int rank;
|
|---|
| 29 | MPI_Comm_rank( MPI_COMM_WORLD, &rank );
|
|---|
| 30 | fprintf( stderr, "[%d] inout[0] = %d, in[0] = %d\n", rank, inoutvec[0], invec[0] );fflush(stderr);
|
|---|
| 31 | inoutvec[i] = BAD_ANSWER;
|
|---|
| 32 | }
|
|---|
| 33 | else
|
|---|
| 34 | inoutvec[i] = invec[i];
|
|---|
| 35 | }
|
|---|
| 36 | }
|
|---|
| 37 |
|
|---|
| 38 | int main( int argc, char **argv )
|
|---|
| 39 | {
|
|---|
| 40 | int rank, size, i;
|
|---|
| 41 | int data;
|
|---|
| 42 | int errors=0;
|
|---|
| 43 | int result = -100;
|
|---|
| 44 | int correct_result;
|
|---|
| 45 | MPI_Op op_assoc, op_addem;
|
|---|
| 46 | MPI_Comm comm=MPI_COMM_WORLD;
|
|---|
| 47 |
|
|---|
| 48 | MPI_Init( &argc, &argv );
|
|---|
| 49 | MPI_Op_create( (MPI_User_function *)assoc, 0, &op_assoc );
|
|---|
| 50 | MPI_Op_create( (MPI_User_function *)addem, 1, &op_addem );
|
|---|
| 51 |
|
|---|
| 52 | /* Run this for a variety of communicator sizes */
|
|---|
| 53 |
|
|---|
| 54 | MPI_Comm_rank( comm, &rank );
|
|---|
| 55 | MPI_Comm_size( comm, &size );
|
|---|
| 56 |
|
|---|
| 57 | data = rank;
|
|---|
| 58 |
|
|---|
| 59 | correct_result = 0;
|
|---|
| 60 | for (i=0;i<=rank;i++)
|
|---|
| 61 | correct_result += i;
|
|---|
| 62 |
|
|---|
| 63 | MPI_Scan ( &data, &result, 1, MPI_INT, MPI_SUM, comm );
|
|---|
| 64 | if (result != correct_result) {
|
|---|
| 65 | fprintf( stderr, "[%d] Error suming ints with scan\n", rank );fflush(stderr);
|
|---|
| 66 | errors++;
|
|---|
| 67 | }
|
|---|
| 68 | MPI_Scan ( &data, &result, 1, MPI_INT, MPI_SUM, comm );
|
|---|
| 69 | if (result != correct_result) {
|
|---|
| 70 | fprintf( stderr, "[%d] Error summing ints with scan (2)\n", rank );fflush(stderr);
|
|---|
| 71 | errors++;
|
|---|
| 72 | }
|
|---|
| 73 |
|
|---|
| 74 | data = rank;
|
|---|
| 75 | result = -100;
|
|---|
| 76 | MPI_Scan ( &data, &result, 1, MPI_INT, op_addem, comm );
|
|---|
| 77 | if (result != correct_result) {
|
|---|
| 78 | fprintf( stderr, "[%d] Error summing ints with scan (userop)\n", rank );fflush(stderr);
|
|---|
| 79 | errors++;
|
|---|
| 80 | }
|
|---|
| 81 |
|
|---|
| 82 | MPI_Scan ( &data, &result, 1, MPI_INT, op_addem, comm );
|
|---|
| 83 | if (result != correct_result) {
|
|---|
| 84 | fprintf( stderr, "[%d] Error summing ints with scan (userop2)\n", rank );fflush(stderr);
|
|---|
| 85 | errors++;
|
|---|
| 86 | }
|
|---|
| 87 | result = -100;
|
|---|
| 88 | data = rank;
|
|---|
| 89 | MPI_Scan ( &data, &result, 1, MPI_INT, op_assoc, comm );
|
|---|
| 90 | if (result == BAD_ANSWER) {
|
|---|
| 91 | fprintf( stderr, "[%d] Error scanning with non-commutative op\n", rank );fflush(stderr);
|
|---|
| 92 | errors++;
|
|---|
| 93 | }
|
|---|
| 94 |
|
|---|
| 95 | MPI_Op_free( &op_assoc );
|
|---|
| 96 | MPI_Op_free( &op_addem );
|
|---|
| 97 |
|
|---|
| 98 | MPI_Finalize();
|
|---|
| 99 | return errors;
|
|---|
| 100 | }
|
|---|