From b590e7650c9b6c0df2f86f92216d1ed90788e231 Mon Sep 17 00:00:00 2001
From: michaelhans <13518056@std.stei.itb.ac.id>
Date: Fri, 5 Mar 2021 23:10:11 +0700
Subject: [PATCH] Testing MPI Program

---
 src/BubbleSort.c        |  48 +++++++++++++++
 src/Coba.c              |  95 +++++++++++++++++++++++++++++
 src/MPI_Communication.c |  25 ++++++++
 src/MPI_HelloWorld.c    |  30 ++++------
 src/MPI_QuickSort.c     | 129 ++++++++++++++++++++++++++++++++++++++++
 src/MST_Serial.c        |   3 -
 src/QuickSort.c         |   7 ++-
 src/Test.c              |  44 ++++++++++++++
 src/hello               | Bin 8600 -> 0 bytes
 9 files changed, 357 insertions(+), 24 deletions(-)
 create mode 100644 src/BubbleSort.c
 create mode 100644 src/Coba.c
 create mode 100644 src/MPI_Communication.c
 create mode 100644 src/MPI_QuickSort.c
 create mode 100644 src/Test.c
 delete mode 100755 src/hello

diff --git a/src/BubbleSort.c b/src/BubbleSort.c
new file mode 100644
index 0000000..8b752e4
--- /dev/null
+++ b/src/BubbleSort.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+// Bubble Sort
+void bubbleSort(int arr[], int n)
+{
+    int i, j;
+    for (i = 0; i < n - 1; i++){
+        for (j = 0; j < n - i - 1; j++){
+            if (arr[j] > arr[j + 1])
+            {
+                int temp = arr[j];
+                arr[j] = arr[j + 1];
+                arr[j + 1] = temp;
+            }
+        }
+    }
+}
+
+// Menuliskan array ke layar
+void PrintArray(int T[], int a, int b)
+{
+    for (int i = a; i <= b - 1; i++)
+    {
+        printf("%d ", T[i - 1]);
+    }
+    printf("%d\n", T[b - 1]);
+}
+
+int main()
+{
+    int T[5000];
+    int N;
+    scanf("%d", &N);
+    for (int i = 0; i < N; i++)
+    {
+        scanf("%d", &T[i]);
+    }
+
+    PrintArray(T, 1, N);
+    int t = clock();
+    bubbleSort(T, N);
+    t = clock() - t;
+    printf("Waktu Eksekusi: %f ms\n", ((double)t) / CLOCKS_PER_SEC * 1000);
+    return 0;
+}
\ No newline at end of file
diff --git a/src/Coba.c b/src/Coba.c
new file mode 100644
index 0000000..3a98195
--- /dev/null
+++ b/src/Coba.c
@@ -0,0 +1,95 @@
+#include <mpi.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+// Menuliskan array ke layar
+void PrintArray(int T[], int a, int b)
+{
+    for (int i = a; i <= b - 1; i++)
+    {
+        printf("%d ", T[i - 1]);
+    }
+    printf("%d\n", T[b - 1]);
+}
+
+// Melakukan partisi sembari menukar value dengan pivot ke-i
+void Partisi(int T[], int i, int j, int *k)
+{
+    int pivot = T[i - 1];
+    int p = i;
+    int q = j;
+    while (p <= q)
+    {
+        while (T[p - 1] < pivot)
+        {
+            p++;
+        }
+        while (T[q - 1] > pivot)
+        {
+            q--;
+        }
+        if (p < q)
+        {
+            int temp = T[p - 1];
+            T[p - 1] = T[q - 1];
+            T[q - 1] = temp;
+            p++;
+            q--;
+        }
+        else if (p == q)
+        {
+            p++;
+        }
+    }
+    *k = q;
+}
+
+// Mengurutkan array dengan menggunakan Quick Sort
+void SequentialQuickSort(int T[], int i, int j)
+{
+    int k;
+    if (i < j)
+    {
+        Partisi(T, i, j, &k);
+        SequentialQuickSort(T, i, k);
+        SequentialQuickSort(T, k + 1, j);
+    }
+}
+
+int main()
+{
+    int my_rank, comm_sz, n;
+    int T[5000];
+    int N;
+
+    MPI_Init(NULL, NULL);
+    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
+
+    if (my_rank == 0){
+        scanf("%d", &N);
+        for (int i = 0; i < N; i++)
+        {
+            scanf("%d", &T[i]);
+        }
+        printf("Hello World");
+        double t = MPI_Wtime();
+        // QuickSort(T, 1, N);
+        // MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        // MPI_Bcast(&T, 5000, MPI_INT, 0, MPI_COMM_WORLD);
+        MPI_Send(&T, 5000, MPI_INT, 0, 0, MPI_COMM_WORLD);
+        printf("Hello World");
+        t = MPI_Wtime() - t;
+        printf("Waktu Eksekusi: %.4f ms\n", t / CLOCKS_PER_SEC * 1000);
+        
+    } else {
+        // MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        // MPI_Bcast(&T, 5000, MPI_INT, 0, MPI_COMM_WORLD);
+        MPI_Recv(&T, 5000, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+        // printf("Process %d: After MPI_Bcast, value is %d\n", my_rank, N);
+    }
+
+    PrintArray(T, 1, N);
+    return 0;
+}
\ No newline at end of file
diff --git a/src/MPI_Communication.c b/src/MPI_Communication.c
new file mode 100644
index 0000000..70dc805
--- /dev/null
+++ b/src/MPI_Communication.c
@@ -0,0 +1,25 @@
+#include <mpi.h>
+#include <stdio.h>
+
+int main()
+{
+    int id, size, x;
+
+    MPI_Init(NULL, NULL);
+    MPI_Comm_size(MPI_COMM_WORLD, &size);
+    MPI_Comm_rank(MPI_COMM_WORLD, &id);
+
+    // P0 mengirim pesan x ke P1
+    // P1 menerima pesan dari P0, disimpan ke x
+    if (id == 0) {
+        x = 6;
+        MPI_Send(&x, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
+    }
+    if (id == 1)
+        MPI_Recv(&x, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, NULL);
+
+    printf("P[%d] x: %d\n", id, x);
+
+    MPI_Finalize();
+    return 0;
+}
\ No newline at end of file
diff --git a/src/MPI_HelloWorld.c b/src/MPI_HelloWorld.c
index 7146ffd..22c55b9 100644
--- a/src/MPI_HelloWorld.c
+++ b/src/MPI_HelloWorld.c
@@ -1,27 +1,17 @@
 #include <mpi.h>
 #include <stdio.h>
 
-int main(int argc, char** argv) {
-    // Initialize the MPI environment
-    MPI_Init(NULL, NULL);
+int main(int argc, char **argv)
+{
+    int size, id;
 
-    // Get the number of processes
-    int world_size;
-    MPI_Comm_size(MPI_COMM_WORLD, &world_size);
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &size);
+    MPI_Comm_rank(MPI_COMM_WORLD, &id);
 
-    // Get the rank of the process
-    int world_rank;
-    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
-
-    // Get the name of the processor
-    char processor_name[MPI_MAX_PROCESSOR_NAME];
-    int name_len;
-    MPI_Get_processor_name(processor_name, &name_len);
-
-    // Print off a hello world message
-    printf("Hello world from processor %s, rank %d out of %d processors\n",
-           processor_name, world_rank, world_size);
-
-    // Finalize the MPI environment.
+    if (id > 0){
+        printf("Hello world!(%d)\n", id);
+    }
     MPI_Finalize();
+    return 0;
 }
\ No newline at end of file
diff --git a/src/MPI_QuickSort.c b/src/MPI_QuickSort.c
new file mode 100644
index 0000000..b8fcceb
--- /dev/null
+++ b/src/MPI_QuickSort.c
@@ -0,0 +1,129 @@
+#include "mpi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+// #include <omp.h>
+
+void initArray(int *arr, int n) {
+	int i;
+	for (i = 0; i < n; ++i)
+	{
+		arr[i] = rand() % n;
+	}
+}
+
+void printArray(int *arr, int n) {
+	int i;
+	for (i = 0; i < n; ++i)
+	{
+		printf("%d\n", arr[i]);
+	}
+}
+
+void swap(int *arr, int i, int j) {
+	int temp = arr[i];
+	arr[i] = arr[j];
+	arr[j] = temp;
+}
+
+void quicksortNormal(int *arr, int lo, int hi) {
+	if (lo < hi) {
+		int x = arr[lo];
+		int pivot = lo;
+		for (int i = lo + 1; i < hi; ++i)
+		{
+			if (arr[i] <= x) {
+				pivot++;
+				swap(arr, pivot, i);
+			}
+		}
+		swap(arr, lo, pivot);
+
+		quicksortNormal(arr, lo, pivot);
+		quicksortNormal(arr, pivot + 1, hi);
+	}
+}
+
+void quicksort(int *arr, int lo, int hi, int rank, int numtasks, int rank_index) {
+	int dest = rank + (1 << rank_index);
+
+	if (dest >= numtasks) {
+		quicksortNormal(arr,lo,hi);
+	} else if (lo < hi) {
+		int x = arr[lo];
+		int pivot = lo;
+
+		for (int i = lo + 1; i < hi; ++i)
+		{
+			if (arr[i] <= x) {
+				pivot++;
+				swap(arr, pivot, i);
+			}
+		}
+		swap(arr, lo, pivot);
+
+		if (pivot - lo > hi - pivot - 1) {
+			MPI_Send(&arr[pivot + 1], hi - pivot - 1, MPI_INT, dest, 1, MPI_COMM_WORLD);
+			quicksort(arr, lo, pivot, rank, numtasks, rank_index + 1);
+			MPI_Recv(&arr[pivot + 1], hi - pivot - 1, MPI_INT, dest, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+		} else {
+			MPI_Send(&arr[lo], pivot - lo, MPI_INT, dest, 1, MPI_COMM_WORLD);
+			quicksort(arr, pivot + 1, hi, rank, numtasks, rank_index + 1);
+			MPI_Recv(&arr[lo], pivot - lo, MPI_INT, dest, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);	
+		}
+	}
+}
+
+int main(int argc, char** argv) {
+	srand(1707);
+	int numtasks, rank;
+	int *tempArr;
+	MPI_Init(&argc,&argv);
+	MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
+	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+	MPI_Status msg;
+
+	printf("%d rank\n", rank);
+	if (rank == 0) {
+		int n;
+		int arr[n];
+
+		scanf("%d", &n);
+        // for (int i = 0; i < n; i++)
+        // {
+        //     scanf("%d", &arr[i]);
+        // }
+
+        initArray(arr, n);
+
+		double start = MPI_Wtime();
+        printf("%d rank\n", rank);
+		quicksort(arr, 0, n, rank, numtasks, 0);
+		double finish = MPI_Wtime();
+
+		printArray(arr, n);
+		printf("N: %d\n", n);
+		printf("Time: %.4f seconds\n", finish-start);
+
+	} else {
+		int rc;
+		int arrSize;
+		int source;
+		int index_count = 0;
+		while(1 << index_count <= rank)
+    		index_count ++; 
+
+		rc = MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &msg);
+		rc = MPI_Get_count(&msg, MPI_INT, &arrSize);
+		source = msg.MPI_SOURCE;
+
+		tempArr = (int *) malloc(sizeof(int)*arrSize);
+		rc = MPI_Recv(tempArr, arrSize, MPI_INT, source, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+		quicksort(tempArr, 0, arrSize, rank, numtasks, index_count);
+		rc = MPI_Send(tempArr, arrSize, MPI_INT, source, 1, MPI_COMM_WORLD);
+		free(tempArr);
+	}
+	printf("LOL %d\n", rank);
+	MPI_Finalize();
+	return 0;
+}
diff --git a/src/MST_Serial.c b/src/MST_Serial.c
index 78971dd..1da7b06 100644
--- a/src/MST_Serial.c
+++ b/src/MST_Serial.c
@@ -185,10 +185,7 @@ void KruskalMST(Graph *graph, Edge result[], int *e)
     bubbleSort(graph->edge, graph->E, 1);
     // Step 2: Allocate memory for creating V subsets
     Subset *subsets = CreateSubset(V);
-<<<<<<< HEAD
 
-=======
->>>>>>> fd8239d3b13d39b3a279991ba4a69031b1378216
     while (((*e) < V - 1) && (i < graph->E))
     {
         // Pick the smallest edge of the graph
diff --git a/src/QuickSort.c b/src/QuickSort.c
index 0074171..58e61cc 100644
--- a/src/QuickSort.c
+++ b/src/QuickSort.c
@@ -1,4 +1,7 @@
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
 
 // Menuliskan array ke layar
 void PrintArray(int T[], int a, int b)
@@ -67,7 +70,9 @@ int main()
     }
 
     PrintArray(T, 1, N);
+    int t = clock();
     QuickSort(T, 1, N);
-    PrintArray(T, 1, N);
+    t = clock() - t;
+    printf("Waktu Eksekusi: %f ms\n", ((double)t) / CLOCKS_PER_SEC * 1000);
     return 0;
 }
\ No newline at end of file
diff --git a/src/Test.c b/src/Test.c
new file mode 100644
index 0000000..bf7e5e1
--- /dev/null
+++ b/src/Test.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include "mpi.h"
+
+
+////////////
+//MPI_Bcast
+////////////
+//
+// int MPI_Bcast( void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm )
+//
+// This example simply uses MPI_Bcast to broadcast a read in value to all other processes from root process
+//
+// example usage:
+//		compile: mpicc -o mpi_bcast mpi_bcast.c
+//		run: mpirun -n 4 mpi_bcast
+//
+int main(argc, argv)
+int argc;
+char **argv;
+{
+	int rank, value;
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank); //what rank is the current processor
+
+    if (rank == 0) {
+        // if root process we read the value to broadcast
+        printf("Enter a number to broadcast:\n");
+	    scanf("%d", &value);
+    } else {
+    	printf("process %d: Before MPI_Bcast, value is %d\n", rank, value); 
+	}
+
+    // each processor calls MPI_Bcast, data is broadcast from root processor and ends up in everyone value variable
+    // root process uses MPI_Bcast to broadcast the value, each other process uses MPI_Bcast to receive the broadcast value
+    MPI_Bcast(&value, 1, MPI_INT, 0, MPI_COMM_WORLD);
+
+    printf("process %d: After MPI_Bcast, value is %d\n", rank, value);
+
+    MPI_Finalize();
+
+	return 0;
+}
\ No newline at end of file
diff --git a/src/hello b/src/hello
deleted file mode 100755
index 1de23036653bc3c34fc555ce1c6d1e0e66f45edb..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 8600
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
JQBkM;zX8%^JNN(q

-- 
GitLab