]> git.somenet.org - pub/jan/parprog.git/blob - scan/scan.c
unsigned long bla = -1; ... yeah!
[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 <sys/stat.h>
11 #include <mpi.h>
12 #include "scan.h"
13
14 // tag for control messages
15 #define KEY 1337 
16
17 /* This one's binary name. */
18 char* binname = "unset";
19
20 void usage () {
21         fprintf(stderr, "\nUsage: mpirun -node 1-32 -nnp 1 %s [-f <string>] [-n <number>]\n", binname);
22         fprintf(stderr, "\t -f: set the filename of the randfile. (defaults to \"numlist.bin\")\n");
23         fprintf(stderr, "\t -n: set the number count to read from randfile. (defaults to 0 = read all)\n");
24 #ifdef DEBUG
25         fprintf(stderr, "***** BIG RED WARNING: COMPILED WITH XDEBUG - YOU ARE ON YOUR OWN! *****\n");
26 #endif
27 #ifdef DEBUG
28         fprintf(stderr, "*** COMPILED WITH DEBUG - size is limited to 64 ***\n");
29         fprintf(stderr, "Compile with XDEBUG or without DEBUG to get past this limit.\n");
30         fprintf(stderr, "You might want to compile this without the DEBUG flag to get less noice.\n");
31 #endif
32         fprintf(stderr, "\n");
33 }
34
35
36 void array_contents(unsigned long arr[], unsigned long size){
37         fprintf(stdout, "[%li", arr[0]);
38         for(unsigned long i = 1; i < size; i++){
39                 fprintf(stdout, ", %li", arr[i]);
40         }
41         fprintf(stdout, "]\n");
42 }
43
44
45 int main(int argc, char *argv[]){
46         int tmp;
47         int tmp2;
48         FILE *file = NULL;
49         MPI_Request request;
50         unsigned long blocksize;
51         unsigned long *databuf;
52
53         /* timings. */
54         double startTime = 0;
55         double prepTime = 0;
56         double algoTime = 0;
57         double postpTime = 0;
58         double endTime = 0;
59
60         /* options */
61         unsigned long size = 0;
62         char *filename = "numlist.bin";
63
64         /* store out name for usage(); */
65         binname = argv[0];
66
67         /* node info stuff*/
68         int rank, nodes;
69         char name[MPI_MAX_PROCESSOR_NAME];
70         MPI_Init(&argc,&argv);
71         MPI_Comm_size(MPI_COMM_WORLD,&nodes);
72         MPI_Comm_rank(MPI_COMM_WORLD,&rank);
73         MPI_Get_processor_name(name,&tmp);
74 #ifdef DEBUG
75         fprintf(stderr, "***** BIG RED WARNING: COMPILED WITH XDEBUG - YOU ARE ON YOUR OWN! *****\n");
76 #endif
77 #ifdef DEBUG
78         fprintf(stderr, "*** COMPILED WITH DEBUG - size is limited to 64 ***\n");
79         fprintf(stderr, "Compile with XDEBUG or without DEBUG to get past this limit.\n");
80         fprintf(stdout, "[%d/%d:%s] openMPI initialised.\n",rank,nodes,name);
81 #endif
82
83         /* getopt stuff */
84         int c;
85         opterr = 0;
86         while ((c = getopt (argc, argv, "n:f:")) != -1) switch (c){
87                 case 'n':
88                         size = strtoul (optarg,NULL,0);
89                         break;
90                 case 'f':
91                         filename = optarg;
92                         break;
93                 case '?':
94                         if (optopt == 'f' || optopt == 'n')
95                                 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
96                         else if (isprint (optopt))
97                                 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
98                         else
99                                 fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
100                         if (rank == 0)usage();
101                         MPI_Finalize();
102                         exit(2);
103                         
104                 default:
105                         if (rank == 0)usage();
106                         MPI_Finalize();
107                         exit(2);
108         }
109
110         /* sanize size, calculate blocksize, init databuf. */
111         if ((file = fopen(filename, "r"))) {
112                 fclose(file);
113                 file = NULL;
114                 struct stat st;
115                 stat(filename, &st);
116                 if (size <= 0 || size > st.st_size){
117                         size = st.st_size;
118                 }
119 #ifdef DEBUG
120 #ifndef XDEBUG
121                 if (size > 64) size = 64;
122 #endif
123 #endif
124         }else{
125                 if(rank == 0){
126                         fprintf (stdout, "[%d/%d:%s] File %s does not exist.\n",rank,nodes,name,filename);
127                         usage();
128                 }
129                 MPI_Finalize();
130                 exit(3);
131         }
132
133         databuf = malloc(size * sizeof(unsigned long));
134         if(databuf == NULL) {
135                 fprintf(stdout, "[%d/%d:%s] malloc for databuf failed.\n",rank,nodes,name);
136                 MPI_Finalize();
137                 exit(2);
138         }
139
140         blocksize = size/nodes;
141         if(blocksize*nodes < size){
142                 blocksize++;
143                 if(rank == 0)
144                         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);
145         }
146
147         if(rank == 0){
148                 fprintf(stdout, "[%d/%d:%s] s: %li n: %d bs: %li n*b: %li n*(b+1): %li\n",rank,nodes,name,size,nodes,blocksize,nodes*blocksize, nodes*(blocksize+1));
149
150                 /* read file. */
151                 if ((file = fopen(filename, "r"))) {
152                         for (unsigned long i = 0; i < size; i++) {
153                                 databuf[i] = fgetc(file);
154                         }
155                         fclose(file);
156                 }else{
157                         fprintf (stdout, "[%d/%d:%s] File %s could not be read.\n",rank,nodes,name,filename);
158                         usage();
159                         MPI_Finalize();
160                         exit(3);
161                 }
162
163                 fprintf(stdout, "[%d/%d:%s] file read - distributing work.\n",rank,nodes,name);
164                 startTime = MPI_Wtime();
165                 MPI_Isend(databuf, size-1, MPI_LONG, 0, KEY, MPI_COMM_WORLD, &request);
166         }
167
168         /* stuff done by all nodes */
169         if (startTime == 0) startTime = MPI_Wtime();
170         tmp = rank -1;
171         if(tmp < 0) tmp = 0;
172         MPI_Recv(databuf, size, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
173
174         /* propagate data, if not last node. */
175         if(rank +1 < nodes) MPI_Send(databuf, size, MPI_LONG, rank+1, KEY, MPI_COMM_WORLD);
176         prepTime = MPI_Wtime();
177
178         /* do processing here. */
179         for(unsigned long i = (rank*blocksize+1); i < ((rank+1)*blocksize) && i < size; i++){
180                 databuf[i] = databuf[(i-1)] + databuf[i];
181         }
182         algoTime = MPI_Wtime();
183 #ifdef DEBUG
184         fprintf(stdout, "[%d/%d:%s] proc array ",rank,nodes,name);
185         array_contents(databuf, size);
186 #endif
187
188
189         /* receive sums */
190         if(rank != 0){
191                 MPI_Recv(databuf, rank*blocksize, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
192 #ifdef DEBUG
193                 fprintf(stdout, "[%d/%d:%s] rcv array ",rank,nodes,name);
194                 array_contents(databuf, size);
195 #endif
196                 for(unsigned long i = rank*blocksize; i < ((rank+1)*blocksize) && i < size; i++){
197                         databuf[i] += databuf[((rank*blocksize)-1)];
198                 }
199 #ifdef DEBUG
200                 fprintf(stdout, "[%d/%d:%s] added array ",rank,nodes,name);
201                 array_contents(databuf, size);
202 #endif
203         }
204         postpTime = MPI_Wtime();
205
206         tmp = rank +1;
207         if(tmp >= nodes) tmp = 0;
208         tmp2 = ((rank+1)*blocksize);
209         if(tmp2 > size) tmp2 = size;
210         MPI_Send(databuf, tmp2, MPI_LONG, tmp, KEY, MPI_COMM_WORLD);
211
212         /* receive result by root */
213         if(rank == 0){
214                 MPI_Recv(databuf, size, MPI_LONG, nodes-1, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
215                 endTime = MPI_Wtime();
216                 fprintf(stdout, "[%d/%d:%s] result: %li\n",rank,nodes,name,databuf[size-1]);
217 #ifdef DEBUG
218                 fprintf(stdout, "[%d/%d:%s] res array ",rank,nodes,name);
219                 array_contents(databuf, size);
220 #endif
221         }
222
223         if(endTime == 0) endTime = MPI_Wtime();
224         fprintf(stdout, "[%d/%d:%s] timings: prep:%f algo:%f postp:%f end:%f\n",rank,nodes,name,prepTime-startTime,algoTime-startTime,postpTime-startTime,endTime-startTime);
225         MPI_Finalize();
226         return 0;
227 }
228