]> git.somenet.org - pub/jan/parprog.git/blob - scan/scan.c
distributed prefixsum
[pub/jan/parprog.git] / scan / scan.c
1 /*
2  * Inclusive scan
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <ctype.h>
8 #include <getopt.h>
9 #include <unistd.h>
10 #include <mpi.h>
11 #include "scan.h"
12
13 // tag for control messages
14 #define KEY 1234 
15
16 void array_contents ( unsigned long arr[], unsigned long size ) {
17         fprintf (stdout, "[%li", arr[0]);
18         for (unsigned long i = 1; i < size; i++) {
19                 fprintf (stdout, ", %li", arr[i]);
20         }
21         fprintf (stdout, "]\n");
22 }
23
24
25 int main(int argc, char *argv[]){
26   int tmp;
27   int tmp2;
28
29   /* node info stuff*/
30   int rank, nodes;
31   char name[MPI_MAX_PROCESSOR_NAME];
32   MPI_Init(&argc,&argv);
33   MPI_Comm_size(MPI_COMM_WORLD,&nodes);
34   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
35   MPI_Get_processor_name(name,&tmp);
36   fprintf(stdout, "[%d/%d:%s] openMPI initialised.\n",rank,nodes,name);
37
38   /* data */
39   unsigned long size = 18;
40   unsigned long blocksize = size/nodes;
41   if(blocksize*nodes < size){
42     blocksize++;
43     fprintf(stdout, "[%d/%d:%s] perfect split impossible: n:%d, s:%li ==> bs:%li (off: %li)\n",rank,nodes,name,nodes,size,blocksize,(nodes*blocksize)-size);
44   }
45
46   unsigned long databuf[size];
47
48   /* temp stuff */
49   MPI_Status status;
50   MPI_Request request;
51
52   /* stuff done by root */
53   if (rank == 0) {
54     fprintf(stdout, "[%d/%d:%s] I am root. Size: %li nodes: %d blocksize: %li (n*b: %li) (n*b+1: %li)- reading data...\n",rank,nodes,name,size,nodes,blocksize,nodes*blocksize, nodes*(blocksize+1));
55     for (unsigned long i = 0; i < size; i++) {
56       databuf[i]=10;
57     }
58     MPI_Isend(&databuf, size-1, MPI_LONG, 0, KEY, MPI_COMM_WORLD, &request);
59   }
60
61  //   MPI_Recv(&databuf,1,MPI_INT,nodes-1,KEY,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
62   /* stuff done by all others */
63   tmp = rank -1;
64   if (tmp  < 0)tmp = 0;
65   MPI_Recv(&databuf, size, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
66
67   /* propagate data, if not last node. */
68   if(rank +1 < nodes) MPI_Send(&databuf, size, MPI_LONG, rank+1, KEY, MPI_COMM_WORLD);
69
70   /* do processing here. */
71   for (unsigned long i = (rank*blocksize+1); i < ((rank+1)*blocksize) && i < size; i++) {
72     databuf[i] = databuf[(i-1)] + databuf[i];
73   }
74   fprintf(stdout, "[%d/%d:%s] proc array ",rank,nodes,name);
75   array_contents(databuf, size);
76
77
78   /* receive sums */
79   if (rank != 0){
80     MPI_Recv(&databuf, rank*blocksize, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
81     fprintf(stdout, "[%d/%d:%s] rcv array ",rank,nodes,name);
82     array_contents(databuf, size);
83     for (unsigned long i = rank*blocksize; i < ((rank+1)*blocksize); i++) {
84       databuf[i] += databuf[((rank*blocksize)-1)];
85     }
86     fprintf(stdout, "[%d/%d:%s] added array ",rank,nodes,name);
87     array_contents(databuf, size);
88   }
89
90   tmp = rank +1;
91   if (tmp  >= nodes)tmp = 0;
92   tmp2 = ((rank+1)*blocksize);
93   if (tmp2  > size)tmp2 = size;
94   MPI_Send(&databuf, tmp2, MPI_LONG, tmp, KEY, MPI_COMM_WORLD);
95
96   /* receive result by root */
97   if (rank == 0) {
98     MPI_Recv(&databuf, size, MPI_LONG, nodes-1, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
99     fprintf(stdout, "[%d/%d:%s] I AM ROOT! got data from %d.\n",rank,nodes,name,nodes-1);
100     fprintf(stdout, "[%d/%d:%s] result array ",rank,nodes,name);
101     array_contents(databuf, size);
102   }
103
104   MPI_Finalize();
105   return 0;
106 }