From 727fe9a8642adeca4dcc7087682397b97938ad97 Mon Sep 17 00:00:00 2001
From: Jan Vales <e0726236@jupiter.par.tuwien.ac.at>
Date: Sun, 29 Jan 2012 22:07:45 +0100
Subject: [PATCH] distributed prefixsum

---
 scan/Makefile |   0
 scan/scan.c   | 107 +++++++++++++++++++++++++++++++++++++++++---------
 scan/scan.h   |   0
 3 files changed, 88 insertions(+), 19 deletions(-)
 mode change 100644 => 100755 scan/Makefile
 mode change 100644 => 100755 scan/scan.c
 mode change 100644 => 100755 scan/scan.h

diff --git a/scan/Makefile b/scan/Makefile
old mode 100644
new mode 100755
diff --git a/scan/scan.c b/scan/scan.c
old mode 100644
new mode 100755
index ea3dd47..4fe6578
--- a/scan/scan.c
+++ b/scan/scan.c
@@ -4,34 +4,103 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include "scan.h"
+#include <ctype.h>
+#include <getopt.h>
+#include <unistd.h>
 #include <mpi.h>
+#include "scan.h"
 
-#define KEY 1234 // tag for control messages
+// tag for control messages
+#define KEY 1234 
 
-int main(int argc, char *argv[])
-{
-  int rank, size;
-  int prev;
-  char name[MPI_MAX_PROCESSOR_NAME];
-  int nlen;
+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");
+}
 
-  MPI_Init(&argc,&argv);
 
-  // get rank and size from communicator
-  MPI_Comm_size(MPI_COMM_WORLD,&size);
+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];
 
-  MPI_Get_processor_name(name,&nlen);
+  /* temp stuff */
+  MPI_Status status;
+  MPI_Request request;
 
-  if (rank==0) {
-    printf("Rank %d initializing, total %d\n",rank,size);
-  } else {
-    MPI_Recv(&prev,1,MPI_INT,rank-1,KEY,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
-    printf("Rank %d on %s received from %d, passing on\n",rank,name,prev);
+  /* 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);
   }
-  if (rank+1<size) MPI_Send(&rank,1,MPI_INT,rank+1,KEY,MPI_COMM_WORLD);
-      
+
+ //   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;
 }
diff --git a/scan/scan.h b/scan/scan.h
old mode 100644
new mode 100755
-- 
2.43.0