Commit 5ac426f3 authored by ahmad.abdulla's avatar ahmad.abdulla

MPI

parents
# Makefile for MPI program
# Source file
SRC = prefix_sum_mpi.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>
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);
int* local_prefix = (int*)malloc(block_size * sizeof(int));
local_prefix[0] = block_array[0];
// Calculate local prefix sum
for (int i = 1; i < block_size; i++) {
local_prefix[i] = local_prefix[i - 1] + block_array[i];
}
// Perform prefix sum across processes
int* prefix_sums = (int*)malloc(com_size * sizeof(int));
MPI_Gather(&local_prefix[block_size - 1], 1, MPI_INT,prefix_sums, 1, MPI_INT, 0, communicator);
int global_accum = 0;
// Calculate the total prefix sum from prefix sums of all processes
if (my_rank == 0) {
for (int i = 0; i < com_size; i++) {
global_accum += prefix_sums[i];
prefix_sums[i] = global_accum;
}
}
// Broadcast the global prefix sum to all processes
MPI_Bcast(prefix_sums, com_size, MPI_INT, 0, communicator);
// Adjust local prefix sums with the global prefix sum
for (int i = 0; i < block_size; i++) {
block_prefix[i] = local_prefix[i] + prefix_sums[my_rank] - local_prefix[block_size - 1];
}
free(local_prefix);
free(prefix_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 = 64;
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("total Prefixes:\n");
for (int j = 0; j < total_array_size; j++)
printf("%d ", total_prefix[j]);
printf("\n");
// Display block prefixes for each process
printf("\n for each process :\n");
for (int i = 0; i < com_size; i++)
{
printf("Process %d: ", i);
for (int j = 0; j < block_size; j++)
printf("%d ", total_prefix[i * block_size + 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 = Mpi_reduce.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
#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>
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);
// Determine the parent and children ranks in the virtual tree
int parent_rank = (my_rank - 1) / 2;
int left_child_rank = 2 * my_rank + 1;
int right_child_rank = 2 * my_rank + 2;
if(my_rank){
recv_data = (int*)malloc(count * sizeof(int));
}
memset(recv_data, 0, count * sizeof(int));
// Allocate buffers for received data from children
int* left_child_data = (int*)malloc(count * sizeof(int));
int* right_child_data = (int*)malloc(count * sizeof(int));
// Receive data from left child if it exists
if (left_child_rank < com_size) {
MPI_Recv(left_child_data, count, MPI_INT, left_child_rank, 0, communicator, MPI_STATUS_IGNORE);
for (int i = 0; i < count; i++) {
recv_data[i] = left_child_data[i] + recv_data[i];
}
}
// Receive data from right child if it exists
if (right_child_rank < com_size) {
MPI_Recv(right_child_data, count, MPI_INT, right_child_rank, 0, communicator, MPI_STATUS_IGNORE);
for (int i = 0; i < count; i++) {
recv_data[i] = right_child_data[i] + recv_data[i];
}
}
// Combine data with own data (e.g., using addition)
for (int i = 0; i < count; i++) {
recv_data[i] = recv_data[i] + send_data[i];
}
// Send the result to the parent if not the root process
if (my_rank != 0) {
MPI_Send(recv_data, count, MPI_INT, parent_rank, 0, communicator);
}
// Free allocated memory
free(left_child_data);
free(right_child_data);
}
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 = 100; 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("\nsize of array : %d \n", count);
printf("Processing time for reduce tree is: %lf\n", tree_time);
printf("Processing time for reduce sequential is: %lf\n\n", sequential_time);
printf("-------------------------------------------------------------\n\n");
for (int i = 0; i < count; i++) {
if (recv_array_tree[i] != recv_array_sequential[i]) {
printf("At index %i: reduce_tree is %i, reduce_sequential 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;
}
master
slave1 user=mpiuser
slave2 user=mpiuser
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