14 // tag for control messages
17 /* This one's binary name. */
18 char* binname = "unset";
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");
25 fprintf(stderr, "***** BIG RED WARNING: COMPILED WITH XDEBUG - YOU ARE ON YOUR OWN! *****\n");
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");
32 fprintf(stderr, "\nErrorcodes:\n");
33 fprintf(stderr, "\t0: Everything went OK.\n\t1: General error.\n\t2: Getopt/wrong usage error.\n\t3: Inputfile error.\n\t4: Memory error.\n\n");
37 void array_contents(unsigned long arr[], unsigned long size){
38 fprintf(stdout, "[%li", arr[0]);
39 for(unsigned long i = 1; i < size; i++){
40 fprintf(stdout, ", %li", arr[i]);
42 fprintf(stdout, "]\n");
46 int main(int argc, char *argv[]){
52 unsigned long blocksize;
53 unsigned long *databuf;
63 unsigned long size = 0;
64 char *filename = "numlist.bin";
66 /* store out name for usage(); */
71 char name[MPI_MAX_PROCESSOR_NAME];
72 MPI_Init(&argc,&argv);
73 MPI_Comm_size(MPI_COMM_WORLD,&nodes);
74 MPI_Comm_rank(MPI_COMM_WORLD,&rank);
75 MPI_Get_processor_name(name,&tmp);
77 fprintf(stderr, "***** BIG RED WARNING: COMPILED WITH XDEBUG - YOU ARE ON YOUR OWN! *****\n");
80 fprintf(stderr, "*** COMPILED WITH DEBUG - size is limited to 64 ***\n");
81 fprintf(stderr, "Compile with XDEBUG or without DEBUG to get past this limit.\n");
82 fprintf(stdout, "[%d/%d:%s] openMPI initialised.\n",rank,nodes,name);
88 while ((c = getopt (argc, argv, "n:f:")) != -1) switch (c){
90 size = strtoul (optarg,NULL,0);
96 if (optopt == 'f' || optopt == 'n')
97 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
98 else if (isprint (optopt))
99 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
101 fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
102 if (rank == 0)usage();
107 if (rank == 0)usage();
112 /* sanize size, calculate blocksize, init databuf. */
113 if ((file = fopen(filename, "r"))) {
124 if (size > 64) size = 64;
127 if (size < 0 || size > st.st_size){
129 fprintf (stderr, "[%d/%d:%s] Cannot read %li numbers from \"%s\" - only has %li bytes.\n",rank,nodes,name,size,filename,st.st_size);
137 fprintf (stderr, "[%d/%d:%s] File %s does not exist.\n",rank,nodes,name,filename);
144 databuf = malloc(size * sizeof(unsigned long));
145 if(databuf == NULL) {
146 fprintf(stdout, "[%d/%d:%s] malloc for databuf failed.\n",rank,nodes,name);
151 blocksize = size/nodes;
152 if(blocksize*nodes < size){
155 fprintf(stderr, "[%d/%d:%s] perfect split impossible: n:%d, s:%li -> bs:%li (off: %li)\n",rank,nodes,name,nodes,size,blocksize,(nodes*blocksize)-size);
159 fprintf(stdout, "[%d/%d:%s] INFO 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));
162 if ((file = fopen(filename, "r"))) {
163 for (unsigned long i = 0; i < size; i++) {
164 databuf[i] = fgetc(file);
168 fprintf (stderr, "[%d/%d:%s] File %s could not be read.\n",rank,nodes,name,filename);
174 fprintf(stdout, "[%d/%d:%s] file read - distributing work.\n",rank,nodes,name);
176 startTime = MPI_Wtime();
177 MPI_Isend(databuf, size-1, MPI_LONG, 0, KEY, MPI_COMM_WORLD, &request);
180 /* receive work and propagate to next node, if not last node. */
181 if (startTime == 0) startTime = MPI_Wtime();
184 MPI_Recv(databuf, size, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
185 if(rank +1 < nodes) MPI_Send(databuf, size, MPI_LONG, rank+1, KEY, MPI_COMM_WORLD);
186 prepTime = MPI_Wtime();
188 /* do actual work here. */
189 for(unsigned long i = (rank*blocksize+1); i < ((rank+1)*blocksize) && i < size; i++){
190 databuf[i] = databuf[(i-1)] + databuf[i];
192 algoTime = MPI_Wtime();
194 fprintf(stdout, "[%d/%d:%s] proc array ",rank,nodes,name);
195 array_contents(databuf, size);
201 MPI_Recv(databuf, rank*blocksize, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
203 fprintf(stdout, "[%d/%d:%s] rcv array ",rank,nodes,name);
204 array_contents(databuf, size);
206 for(unsigned long i = rank*blocksize; i < ((rank+1)*blocksize) && i < size; i++){
207 databuf[i] += databuf[((rank*blocksize)-1)];
210 fprintf(stdout, "[%d/%d:%s] added array ",rank,nodes,name);
211 array_contents(databuf, size);
214 postpTime = MPI_Wtime();
217 if(tmp >= nodes) tmp = 0;
218 tmp2 = ((rank+1)*blocksize);
219 if(tmp2 > size) tmp2 = size;
220 MPI_Isend(databuf, tmp2, MPI_LONG, tmp, KEY, MPI_COMM_WORLD,&request);
222 /* receive result by root */
224 MPI_Recv(databuf, size, MPI_LONG, nodes-1, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
225 endTime = MPI_Wtime();
226 fprintf(stdout, "[%d/%d:%s] result: %li\n",rank,nodes,name,databuf[size-1]);
227 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);
229 fprintf(stdout, "[%d/%d:%s] res array ",rank,nodes,name);
230 array_contents(databuf, size);
235 if(endTime == 0) endTime = MPI_Wtime();
236 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);
238 MPI_Wait(&request, &status);