HW2: A local only version of the distbitonic

This commit is contained in:
2024-12-28 01:40:43 +02:00
parent 428b50aab7
commit 43dff95f67
10 changed files with 29525 additions and 126 deletions
+106
View File
@@ -0,0 +1,106 @@
/*!
* \file
* \brief Distributed bitonic implementation.
*
* \author
* Christos Choutouridis AEM:8997
* <cchoutou@ece.auth.gr>
*/
#include <vector>
#include <algorithm>
#include <cmath>
#include <cassert>
#include "distbitonic.hpp"
/*!
* Returns the ascending or descending configuration of the node's sequence based on
* the current node (MPI process) and the depth of the sorting network
*
* @param node The current node (MPI process)
* @param depth The total depth of the sorting network (same for each step for a given network)
*
* @return True if we need ascending configuration, false otherwise
*/
bool ascending(size_t node, size_t depth) noexcept {
return !(node & (1 << depth));
}
/*!
* Returns the node's partner for data exchange during the sorting network iterations
*
* @param node The current node
* @param step The step of the sorting network
* @return The node id of the partner for data exchange
*/
size_t partner(size_t node, size_t step) noexcept {
return (node ^ (1 << step));
}
/*!
* Predicate to check if a node keeps the small numbers during the bitonic
* sort network exchange.
*
* @param node The node for which we check
* @param partner The partner of the data exchange
* @param depth The total depth of the sorting network (same for each step for a given network)
* @return True if the node should keep the small values, false otherwise
*/
bool keepsmall(size_t node, size_t partner, size_t depth) noexcept {
assert(node != partner);
return ascending(node, depth) == (node < partner);
}
void exchange(size_t node, size_t partner) {
assert(node != partner);
}
void minmax(AllData_t& data, size_t node, size_t partner, bool keepsmall) {
for (size_t i = 0; i < data[node].size(); ++i) {
if (keepsmall && data[node][i] > data[partner][i])
std::swap(data[node][i], data[partner][i]);
if (!keepsmall && data[node][i] < data[partner][i])
std::swap(data[node][i], data[partner][i]);
}
}
void sort_network(AllData_t& data, size_t nodes, size_t depth) {
for (size_t step = depth; step > 0;) {
--step;
for (size_t node = 0; node < nodes; ++node) {
auto part = partner(node, step);
auto ks = keepsmall(node, part, depth);
if (node < part) {
exchange(node, part);
minmax(data, node, part, ks);
}
}
}
}
void distbitonic(size_t P, AllData_t& data) {
auto p = static_cast<uint32_t>(std::log2(P));
for (size_t node = 0 ; node < P ; ++node) { // Currently we do all nodes here!
// Initially sort to create the half part of a bitonic
if (ascending(node, 0))
std::sort(data[node].begin(), data[node].end(), std::less<>());
else
std::sort(data[node].begin(), data[node].end(), std::greater<>());
}
// Run through sort network using elbow-sort
for (size_t depth = 1; depth <= p; ++depth) {
sort_network(data, P, depth);
for (size_t node = 0 ; node < P ; ++node) { // Currently we do all nodes here!
// elbow-sort here
if (ascending(node, depth))
std::sort(data[node].begin(), data[node].end(), std::less<>());
else
std::sort(data[node].begin(), data[node].end(), std::greater<>());
}
}
}
+78 -12
View File
@@ -1,22 +1,43 @@
/*!
* \file main.cpp
* \file
* \brief Main application file for PDS HW2 (MPI)
*
* \author
* Christos Choutouridis AEM:8997
* <cchoutou@ece.auth.gr>
*/
#include <exception>
#include <iostream>
#include <algorithm> // rand/srand
//#include <ctime> // rand/srand
#if !defined TESTING
#include <mpi.h>
#endif
#include <mpi.h>
#include "matrix.hpp"
#include "distbitonic.hpp"
#include "utils.hpp"
#include "config.h"
//#include "matrix.hpp"
// Global session data
session_t session;
session_t session;
mpi_t mpi;
/*
* Sorting data for up to 8 processes
*/
AllData_t Data {
Data_t (8),
Data_t (8),
Data_t (8),
Data_t (8),
Data_t (8),
Data_t (8),
Data_t (8),
Data_t (8)
};
/*!
* A small command line argument parser
@@ -64,6 +85,9 @@ bool get_options(int argc, char* argv[]){
return status;
}
#if !defined TESTING
int main(int argc, char* argv[]) try {
// try to read command line
if (!get_options(argc, argv))
@@ -72,22 +96,49 @@ int main(int argc, char* argv[]) try {
// Initialize the MPI environment
MPI_Init(NULL, NULL);
#if defined DEBUG
/*
* In case of a debug build we will wait here until sleep_wait
* will reset via debugger. In order to do that the user must attach
* debugger to all processes. For example:
* $> mpirun -np 2 ./<program path>
* $> ps aux | grep <program>
* $> gdb <program> <PID1>
* $> gdb <program> <PID2>
*/
#if defined TESTING
volatile bool sleep_wait = false;
#else
volatile bool sleep_wait = true;
#endif
while (sleep_wait)
sleep(1);
#endif
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
MPI_Comm_size(MPI_COMM_WORLD, reinterpret_cast<int *>(&mpi.world_size));
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
MPI_Comm_rank(MPI_COMM_WORLD, reinterpret_cast<int *>(&mpi.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);
mpi.processor_name = std::string (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);
std::cout << "Hello world from processor: " << mpi.processor_name
<< " rank " << mpi.world_rank
<< " out of " << mpi.world_size << " processors\n";
// std::srand(unsigned(std::time(nullptr)));
// for (auto& v : Data) {
// std::generate(v.begin(), v.end(), std::rand);
// }
//
// distbitonic (2, Data);
// distbitonic (4, Data);
// Finalize the MPI environment.
MPI_Finalize();
@@ -97,4 +148,19 @@ catch (std::exception& e) {
//we probably pollute the user's screen. Comment `cerr << ...` if you don't like it.
std::cerr << "Error: " << e.what() << '\n';
exit(1);
}
}
#else
#include <gtest/gtest.h>
#include <exception>
GTEST_API_ int main(int argc, char **argv) try {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
catch (std::exception& e) {
std::cout << "Exception: " << e.what() << '\n';
}
#endif