From c292175f00747d7c2a52373e8db70cca6448d8a5 Mon Sep 17 00:00:00 2001
From: Jan Vales <e0726236@jupiter.par.tuwien.ac.at>
Date: Mon, 30 Jan 2012 01:32:53 +0100
Subject: [PATCH] mpiscan: schoenere einruekung und getopt + fileread.

---
 scan/scan.c | 254 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 166 insertions(+), 88 deletions(-)

diff --git a/scan/scan.c b/scan/scan.c
index 4fe6578..256c95b 100755
--- a/scan/scan.c
+++ b/scan/scan.c
@@ -7,100 +7,178 @@
 #include <ctype.h>
 #include <getopt.h>
 #include <unistd.h>
+#include <sys/stat.h>
 #include <mpi.h>
 #include "scan.h"
 
 // tag for control messages
-#define KEY 1234 
-
-void array_contents ( unsigned long arr[], unsigned long size ) {
-        fprintf (stdout, "[%li", arr[0]);
-        for (unsigned long i = 1; i < size; i++) {
-                fprintf (stdout, ", %li", arr[i]);
-        }
-        fprintf (stdout, "]\n");
+#define KEY 1337 
+
+/* This one's binary name. */
+char* binname = "unset";
+
+void usage () {
+	fprintf (stderr, "\nUsage: mpirun -node 1-32 -nnp 1 %s [-f <string>] [-n <number>]\n", binname);
+	fprintf (stderr, "\t -f: set the filename of the randfile. (defaults to \"numlist.bin\")\n");
+	fprintf (stderr, "\t -n: set the number count to read from randfile. (defaults to -1 = read all)\n\n");
+}
+
+
+void array_contents(unsigned long arr[], unsigned long size){
+	fprintf(stdout, "[%li", arr[0]);
+	for(unsigned long i = 1; i < size; i++){
+		fprintf(stdout, ", %li", arr[i]);
+	}
+	fprintf(stdout, "]\n");
 }
 
 
 int main(int argc, char *argv[]){
-  int tmp;
-  int tmp2;
-
-  /* node info stuff*/
-  int rank, nodes;
-  char name[MPI_MAX_PROCESSOR_NAME];
-  MPI_Init(&argc,&argv);
-  MPI_Comm_size(MPI_COMM_WORLD,&nodes);
-  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
-  MPI_Get_processor_name(name,&tmp);
-  fprintf(stdout, "[%d/%d:%s] openMPI initialised.\n",rank,nodes,name);
-
-  /* data */
-  unsigned long size = 18;
-  unsigned long blocksize = size/nodes;
-  if(blocksize*nodes < size){
-    blocksize++;
-    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);
-  }
-
-  unsigned long databuf[size];
-
-  /* temp stuff */
-  MPI_Status status;
-  MPI_Request request;
-
-  /* stuff done by root */
-  if (rank == 0) {
-    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));
-    for (unsigned long i = 0; i < size; i++) {
-      databuf[i]=10;
-    }
-    MPI_Isend(&databuf, size-1, MPI_LONG, 0, KEY, MPI_COMM_WORLD, &request);
-  }
-
- //   MPI_Recv(&databuf,1,MPI_INT,nodes-1,KEY,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
-  /* stuff done by all others */
-  tmp = rank -1;
-  if (tmp  < 0)tmp = 0;
-  MPI_Recv(&databuf, size, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-
-  /* propagate data, if not last node. */
-  if(rank +1 < nodes) MPI_Send(&databuf, size, MPI_LONG, rank+1, KEY, MPI_COMM_WORLD);
-
-  /* do processing here. */
-  for (unsigned long i = (rank*blocksize+1); i < ((rank+1)*blocksize) && i < size; i++) {
-    databuf[i] = databuf[(i-1)] + databuf[i];
-  }
-  fprintf(stdout, "[%d/%d:%s] proc array ",rank,nodes,name);
-  array_contents(databuf, size);
-
-
-  /* receive sums */
-  if (rank != 0){
-    MPI_Recv(&databuf, rank*blocksize, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-    fprintf(stdout, "[%d/%d:%s] rcv array ",rank,nodes,name);
-    array_contents(databuf, size);
-    for (unsigned long i = rank*blocksize; i < ((rank+1)*blocksize); i++) {
-      databuf[i] += databuf[((rank*blocksize)-1)];
-    }
-    fprintf(stdout, "[%d/%d:%s] added array ",rank,nodes,name);
-    array_contents(databuf, size);
-  }
-
-  tmp = rank +1;
-  if (tmp  >= nodes)tmp = 0;
-  tmp2 = ((rank+1)*blocksize);
-  if (tmp2  > size)tmp2 = size;
-  MPI_Send(&databuf, tmp2, MPI_LONG, tmp, KEY, MPI_COMM_WORLD);
-
-  /* receive result by root */
-  if (rank == 0) {
-    MPI_Recv(&databuf, size, MPI_LONG, nodes-1, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-    fprintf(stdout, "[%d/%d:%s] I AM ROOT! got data from %d.\n",rank,nodes,name,nodes-1);
-    fprintf(stdout, "[%d/%d:%s] result array ",rank,nodes,name);
-    array_contents(databuf, size);
-  }
-
-  MPI_Finalize();
-  return 0;
+	int tmp;
+	int tmp2;
+	FILE *file = NULL;
+	MPI_Request request;
+	unsigned long blocksize;
+	unsigned long *databuf;
+
+	/* options */
+	unsigned long size = 0;
+	char *filename = "numlist.bin";
+
+	/* store out name for usage(); */
+	binname = argv[0];
+
+	/* node info stuff*/
+	int rank, nodes;
+	char name[MPI_MAX_PROCESSOR_NAME];
+	MPI_Init(&argc,&argv);
+	MPI_Comm_size(MPI_COMM_WORLD,&nodes);
+	MPI_Comm_rank(MPI_COMM_WORLD,&rank);
+	MPI_Get_processor_name(name,&tmp);
+	//fprintf(stdout, "[%d/%d:%s] openMPI initialised.\n",rank,nodes,name);
+
+	/* getopt stuff */
+	int c;
+	opterr = 0;
+	while ((c = getopt (argc, argv, "n:f:")) != -1) switch (c){
+		case 'n':
+			size = strtoul (optarg,NULL,0);
+			break;
+		case 'f':
+			filename = optarg;
+			break;
+		case '?':
+			if (optopt == 'f' || optopt == 'n')
+				fprintf (stderr, "Option -%c requires an argument.\n", optopt);
+			else if (isprint (optopt))
+				fprintf (stderr, "Unknown option `-%c'.\n", optopt);
+			else
+				fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
+			if (rank == 0)usage();
+			MPI_Finalize();
+			exit(2);
+			
+		default:
+			if (rank == 0)usage();
+			MPI_Finalize();
+			exit(2);
+	}
+
+	/* sanize size, calculate blocksize, init databuf. */
+	if ((file = fopen(filename, "r"))) {
+		fclose(file);
+		file = NULL;
+		struct stat st;
+		stat(filename, &st);
+		if (size <= 0 || size > st.st_size){
+			size = st.st_size;
+		}
+	}else{
+		if(rank == 0){
+			fprintf (stdout, "[%d/%d:%s] File %s does not exist.\n",rank,nodes,name,filename);
+			usage();
+		}
+		MPI_Finalize();
+		exit(3);
+	}
+
+	databuf = malloc(size * sizeof(unsigned long));
+	if(databuf == NULL) {
+		fprintf(stdout, "[%d/%d:%s] malloc for databuf failed.\n",rank,nodes,name);
+		MPI_Finalize();
+		exit(2);
+	}
+
+	blocksize = size/nodes;
+	if(blocksize*nodes < size){
+		blocksize++;
+		if(rank == 0)
+			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);
+	}
+
+	if(rank == 0){
+		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));
+
+		/* read file. */
+		if ((file = fopen(filename, "r"))) {
+			for (unsigned long i = 0; i < size; i++) {
+				databuf[i] = fgetc(file);
+			}
+			fclose(file);
+		}else{
+			fprintf (stdout, "[%d/%d:%s] File %s could not be read.\n",rank,nodes,name,filename);
+			usage();
+			MPI_Finalize();
+			exit(3);
+		}
+
+		fprintf(stdout, "[%d/%d:%s] file read - distributing work.\n",rank,nodes,name);
+		MPI_Isend(databuf, size-1, MPI_LONG, 0, KEY, MPI_COMM_WORLD, &request);
+	}
+
+	/* stuff done by all others */
+	tmp = rank -1;
+	if(tmp < 0) tmp = 0;
+	MPI_Recv(databuf, size, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+
+	/* propagate data, if not last node. */
+	if(rank +1 < nodes) MPI_Send(databuf, size, MPI_LONG, rank+1, KEY, MPI_COMM_WORLD);
+
+	/* do processing here. */
+	for(unsigned long i = (rank*blocksize+1); i < ((rank+1)*blocksize) && i < size; i++){
+		databuf[i] = databuf[(i-1)] + databuf[i];
+	}
+	//fprintf(stdout, "[%d/%d:%s] proc array ",rank,nodes,name);
+	//array_contents(databuf, size);
+
+
+	/* receive sums */
+	if(rank != 0){
+		MPI_Recv(databuf, rank*blocksize, MPI_LONG, tmp, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+	//	fprintf(stdout, "[%d/%d:%s] rcv array ",rank,nodes,name);
+	//	array_contents(databuf, size);
+		for(unsigned long i = rank*blocksize; i < ((rank+1)*blocksize) && i < size; i++){
+			databuf[i] += databuf[((rank*blocksize)-1)];
+		}
+	//	fprintf(stdout, "[%d/%d:%s] added array ",rank,nodes,name);
+	//	array_contents(databuf, size);
+	}
+
+	tmp = rank +1;
+	if(tmp >= nodes) tmp = 0;
+	tmp2 = ((rank+1)*blocksize);
+	if(tmp2 > size) tmp2 = size;
+	MPI_Send(databuf, tmp2, MPI_LONG, tmp, KEY, MPI_COMM_WORLD);
+
+	/* receive result by root */
+	if(rank == 0){
+		MPI_Recv(databuf, size, MPI_LONG, nodes-1, KEY, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+		fprintf(stdout, "[%d/%d:%s] result: %li\n",rank,nodes,name,databuf[size-1]);
+//		fprintf(stdout, "[%d/%d:%s] res array ",rank,nodes,name);
+//		array_contents(databuf, size);
+	}
+
+	MPI_Finalize();
+	return 0;
 }
+
-- 
2.43.0