]> git.somenet.org - pub/jan/parprog.git/blob - scan/scan.c
mpiscan: schoenere einruekung und getopt + fileread.
[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 -1 = read all)\n\n");
24 }
25
26
27 void array_contents(unsigned long arr[], unsigned long size){
28         fprintf(stdout, "[%li", arr[0]);
29         for(unsigned long i = 1; i < size; i++){
30                 fprintf(stdout, ", %li", arr[i]);
31         }
32         fprintf(stdout, "]\n");
33 }
34
35
36 int main(int argc, char *argv[]){
37         int tmp;
38         int tmp2;
39         FILE *file = NULL;
40         MPI_Request request;
41         unsigned long blocksize;
42         unsigned long *databuf;
43
44         /* options */
45         unsigned long size = 0;
46         char *filename = "numlist.bin";
47
48         /* store out name for usage(); */
49         binname = argv[0];
50
51         /* node info stuff*/
52         int rank, nodes;
53         char name[MPI_MAX_PROCESSOR_NAME];
54         MPI_Init(&argc,&argv);
55         MPI_Comm_size(MPI_COMM_WORLD,&nodes);
56         MPI_Comm_rank(MPI_COMM_WORLD,&rank);
57         MPI_Get_processor_name(name,&tmp);
58         //fprintf(stdout, "[%d/%d:%s] openMPI initialised.\n",rank,nodes,name);
59
60         /* getopt stuff */
61         int c;
62         opterr = 0;
63         while ((c = getopt (argc, argv, "n:f:")) != -1) switch (c){
64                 case 'n':
65                         size = strtoul (optarg,NULL,0);
66                         break;
67                 case 'f':
68                         filename = optarg;
69                         break;
70                 case '?':
71                         if (optopt == 'f' || optopt == 'n')
72                                 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
73                         else if (isprint (optopt))
74                                 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
75                         else
76                                 fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
77                         if (rank == 0)usage();
78                         MPI_Finalize();
79                         exit(2);
80                         
81                 default:
82                         if (rank == 0)usage();
83                         MPI_Finalize();
84                         exit(2);
85         }
86
87         /* sanize size, calculate blocksize, init databuf. */
88         if ((file = fopen(filename, "r"))) {
89                 fclose(file);
90                 file = NULL;
91                 struct stat st;
92                 stat(filename, &st);
93                 if (size <= 0 || size > st.st_size){
94                         size = st.st_size;
95                 }
96         }else{
97                 if(rank == 0){
98                         fprintf (stdout, "[%d/%d:%s] File %s does not exist.\n",rank,nodes,name,filename);
99                         usage();
100                 }
101                 MPI_Finalize();
102                 exit(3);
103         }
104
105         databuf = malloc(size * sizeof(unsigned long));
106         if(databuf == NULL) {
107                 fprintf(stdout, "[%d/%d:%s] malloc for databuf failed.\n",rank,nodes,name);
108                 MPI_Finalize();
109                 exit(2);
110         }
111
112         blocksize = size/nodes;
113         if(blocksize*nodes < size){
114                 blocksize++;
115                 if(rank == 0)
116                         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);
117         }
118
119         if(rank == 0){
120                 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));
121
122                 /* read file. */
123                 if ((file = fopen(filename, "r"))) {
124                         for (unsigned long i = 0; i < size; i++) {
125                                 databuf[i] = fgetc(file);
126                         }
127                         fclose(file);
128                 }else{
129                         fprintf (stdout, "[%d/%d:%s] File %s could not be read.\n",rank,nodes,name,filename);
130                         usage();
131                         MPI_Finalize();
132                         exit(3);
133                 }
134
135                 fprintf(stdout, "[%d/%d:%s] file read - distributing work.\n",rank,nodes,name);
136                 MPI_Isend(databuf, size-1, MPI_LONG, 0, KEY, MPI_COMM_WORLD, &request);
137         }
138
139         /* stuff done by all others */
140         tmp = rank -1;
141         if(tmp < 0) tmp = 0;
142         MPI_Recv(databuf, size, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
143
144         /* propagate data, if not last node. */
145         if(rank +1 < nodes) MPI_Send(databuf, size, MPI_LONG, rank+1, KEY, MPI_COMM_WORLD);
146
147         /* do processing here. */
148         for(unsigned long i = (rank*blocksize+1); i < ((rank+1)*blocksize) && i < size; i++){
149                 databuf[i] = databuf[(i-1)] + databuf[i];
150         }
151         //fprintf(stdout, "[%d/%d:%s] proc array ",rank,nodes,name);
152         //array_contents(databuf, size);
153
154
155         /* receive sums */
156         if(rank != 0){
157                 MPI_Recv(databuf, rank*blocksize, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
158         //      fprintf(stdout, "[%d/%d:%s] rcv array ",rank,nodes,name);
159         //      array_contents(databuf, size);
160                 for(unsigned long i = rank*blocksize; i < ((rank+1)*blocksize) && i < size; i++){
161                         databuf[i] += databuf[((rank*blocksize)-1)];
162                 }
163         //      fprintf(stdout, "[%d/%d:%s] added array ",rank,nodes,name);
164         //      array_contents(databuf, size);
165         }
166
167         tmp = rank +1;
168         if(tmp >= nodes) tmp = 0;
169         tmp2 = ((rank+1)*blocksize);
170         if(tmp2 > size) tmp2 = size;
171         MPI_Send(databuf, tmp2, MPI_LONG, tmp, KEY, MPI_COMM_WORLD);
172
173         /* receive result by root */
174         if(rank == 0){
175                 MPI_Recv(databuf, size, MPI_LONG, nodes-1, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
176                 fprintf(stdout, "[%d/%d:%s] result: %li\n",rank,nodes,name,databuf[size-1]);
177 //              fprintf(stdout, "[%d/%d:%s] res array ",rank,nodes,name);
178 //              array_contents(databuf, size);
179         }
180
181         MPI_Finalize();
182         return 0;
183 }
184