Commit eca1a5a5 authored by ali's avatar ali

Initial commit

parents
# Makefile for MPI program
# Source file
SRC = prefix_sum.cpp
# number of process
NP = 4
# Compiler
CXX = mpic++
# Executable name
EXE = ./output
all: $(EXE)
$(EXE): $(SRC)
$(CXX) -o $(EXE) $(SRC)
clean:
rm -f $(EXE)
run:
mpirun -np $(NP) -f hosts $(EXE)
\ No newline at end of file
master
slave1 user=mpiuser
slave2 user=mpiuser
#include <mpi.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
#include <mpi.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
void prefix_mpi(int* block_array, int block_size, int* block_prefix, MPI_Comm communicator) {
int my_rank, com_size;
MPI_Comm_rank(communicator, &my_rank);
MPI_Comm_size(communicator, &com_size);
// Calculate prefix sum for the local block
int local_sum = 0;
for (int i = 0; i < block_size; i++) {
local_sum += block_array[i];
block_prefix[i] = local_sum;
}
// Communicate between processes to accumulate and distribute prefix sums
int* all_sums = (int*)malloc(com_size * sizeof(int));
// Gather local sums to root process
MPI_Gather(&local_sum, 1, MPI_INT, all_sums, 1, MPI_INT, 0, communicator);
// Calculate prefix sum of local sums
if (my_rank == 0) {
int global_sum = 0;
for (int i = 0; i < com_size; i++) {
global_sum += all_sums[i];
all_sums[i] = global_sum;
}
}
// Broadcast the global prefix sum to all processes
MPI_Bcast(all_sums, com_size, MPI_INT, 0, communicator);
// Adjust local prefix sums using the global prefix sum
for (int i = 0; i < block_size; i++) {
block_prefix[i] += all_sums[my_rank] - local_sum;
}
free(all_sums);
}
int main(int argc, char** args)
{
// Initialize MPI
MPI_Init(&argc, &args);
int my_rank;
int com_size;
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_size(MPI_COMM_WORLD, &com_size);
// Set the total array size and adjust it for an even distribution among processes
int total_array_size = 32;
if (total_array_size % com_size != 0)
total_array_size = (total_array_size / com_size + 1) * com_size;
// Calculate block size for each process
int block_size = total_array_size / com_size;
// Arrays to store the total array and its prefix sum
int* total_array = NULL;
int* total_prefix = NULL;
// Master process (rank 0) initializes the total array with random values
if (my_rank == 0)
{
total_array = (int*)malloc(total_array_size * sizeof(int));
total_prefix = (int*)malloc(total_array_size * sizeof(int));
for (int i = 0; i < total_array_size; i++)
total_array[i] = rand() % 11;
// Display the generated total array
printf("Total Array: ");
for (int i = 0; i < total_array_size; i++)
printf("%d ", total_array[i]);
printf("\n\n");
}
// Arrays to store the block array and its prefix sum for each process
int* block_array = (int*)malloc(block_size * sizeof(int));
int* block_prefix = (int*)malloc(block_size * sizeof(int));
// Scatter the total array among processes
MPI_Scatter(total_array, block_size, MPI_INT,
block_array, block_size, MPI_INT, 0, MPI_COMM_WORLD);
// Calculate the prefix sum for the block array
prefix_mpi(block_array, block_size, block_prefix, MPI_COMM_WORLD);
// Gather the block prefixes back to the total prefix array on the master process
MPI_Gather(block_prefix, block_size, MPI_INT,
total_prefix, block_size, MPI_INT, 0, MPI_COMM_WORLD);
// Validate the computed prefix sum against the sequential calculation on the master process
int accum = 0;
if (my_rank == 0)
{
// Display block prefixes for all processes
printf("Prefixe sums:\n");
for (int j = 0; j < total_array_size; j++)
printf("%d ", total_prefix[j]);
printf("\n");
// Validate the computed prefix sum against the sequential calculation
for (int i = 1; i < total_array_size; i++)
{
accum += total_array[i - 1];
if (total_prefix[i-1] != accum)
printf("Error at index %i: %i expected, %i computed\n", i, accum, total_prefix[i-1]);
}
printf("Test completed!\n");
free(total_array);
free(total_prefix);
}
// Free allocated memory for block arrays
free(block_array);
free(block_prefix);
// Finalize MPI
MPI_Finalize();
return 0;
}
# Makefile for MPI program
# Source file
SRC = reduce_tree.cpp
# number of process
NP = 12
# Compiler
CXX = mpic++
# Executable name
EXE = ./output
all: $(EXE)
$(EXE): $(SRC)
$(CXX) -o $(EXE) $(SRC)
clean:
rm -f $(EXE)
run:
mpirun -np $(NP) -f mpi_hosts $(EXE)
\ No newline at end of file
master
slave1 user=mpiuser
slave2 user=mpiuser
#include <mpi.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
#include <mpi.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
#include <mpi.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
void reduce_tree(int* send_data, int* recv_data, int count, MPI_Comm communicator) {
int my_rank, com_size;
MPI_Comm_rank(communicator, &my_rank);
MPI_Comm_size(communicator, &com_size);
if(my_rank){
recv_data = (int*)malloc(count * sizeof(int));
}
// Initialize recv_data to 0
memset(recv_data, 0, count * sizeof(int));
int parent = (my_rank - 1) / 2;
int left_child = 2 * my_rank + 1;
int right_child = 2 * my_rank + 2;
// Check if the node has left and right children
bool has_left_child = left_child < com_size;
bool has_right_child = right_child < com_size;
// Temporary buffer for receiving data
// Allocate memory for temporary data
int* temp_data = (int*)malloc(count * sizeof(int));
memset(temp_data, 0, count * sizeof(int));
int* temp_data1 = (int*)malloc(count * sizeof(int));
memset(temp_data1, 0, count * sizeof(int));
// Receive data from left child
if (has_left_child) {
MPI_Recv(temp_data, count, MPI_INT, left_child, 0, communicator, MPI_STATUS_IGNORE);
for (int i = 0; i < count; i++){
recv_data[i] += temp_data[i];
}
free(temp_data);
}
//memset(temp_data, 0, count * sizeof(int));
// Receive data from right child
if (has_right_child) {
MPI_Recv(temp_data1, count, MPI_INT, right_child, 0, communicator, MPI_STATUS_IGNORE);
for (int i = 0; i < count; i++){
recv_data[i] += temp_data1[i];
}
free(temp_data1);
}
// Combine data with own data
for (int i = 0; i < count; i++) {
recv_data[i] += send_data[i];
}
// Send data to the parent
if (my_rank != 0) {
MPI_Send(recv_data, count, MPI_INT, parent, 0, communicator);
}
}
// Rest of your code remains unchanged
void reduce_sequential(
int* send_data,
int* recv_data,
int count,
MPI_Comm communicator)
{
int my_rank;
int com_size;
MPI_Comm_rank(communicator, &my_rank);
MPI_Comm_size(communicator, &com_size);
int* gather_buffer = NULL;
if (my_rank == 0)
{
gather_buffer = (int*) calloc(count * com_size, sizeof(int));
}
MPI_Gather(send_data, count, MPI_INT, gather_buffer, count, MPI_INT, 0, communicator);
if (my_rank == 0)
{
memset(recv_data, 0, count * sizeof(int));
for (int p = 0; p < com_size; p++)
for (int i = 0; i < count; i++)
recv_data[i] += gather_buffer[count * p + i];
free(gather_buffer);
}
}
int main(int argc, char** args)
{
MPI_Init(&argc, &args);
int max_value = 10000000;
int* recv_array_tree = NULL;
int* recv_array_sequential = NULL;
int my_rank;
double sequential_time = 0.0;
double tree_time = 0.0;
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
for (int count = 10; count <= max_value; count *= 10) {
if (my_rank == 0) {
recv_array_tree = (int*) malloc(count * sizeof(int));
recv_array_sequential = (int*) malloc(count * sizeof(int));
}
int* send_array = (int*) malloc(count * sizeof(int));
for (int i = 0; i < count; i++)
send_array[i] = my_rank;
double time1 = 0.0;
double time2 = 0.0;
MPI_Barrier(MPI_COMM_WORLD);
time1 -= MPI_Wtime();
reduce_tree(send_array, recv_array_tree, count, MPI_COMM_WORLD);
time1 += MPI_Wtime();
tree_time = time1;
MPI_Barrier(MPI_COMM_WORLD);
time2 -= MPI_Wtime();
reduce_sequential(send_array, recv_array_sequential, count, MPI_COMM_WORLD);
time2 += MPI_Wtime();
sequential_time = time2;
if (my_rank == 0) {
printf("\nArray size: %d\n", count);
printf("Time taken for sequential reduction: %lf seconds\n", sequential_time);
printf("Time taken for parallel reduction: %lf seconds\n", tree_time);
printf("************ ************ ********** \n\n");
for (int i = 0; i < count; i++) {
if (recv_array_tree[i] != recv_array_sequential[i]) {
printf("At index %i: Parallel reduction result is %i, Sequential reduction result is %i\n",
i, recv_array_tree[i], recv_array_sequential[i]);
}
}
free(recv_array_tree);
free(recv_array_sequential);
}
free(send_array);
}
MPI_Finalize();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment