HW2: A local version of distbubbletonic added

This commit is contained in:
2024-12-28 14:53:13 +02:00
parent 43dff95f67
commit 496ee69f54
5 changed files with 736 additions and 402 deletions
+115 -14
View File
@@ -13,6 +13,19 @@
#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)
* @return True if we need ascending configuration, false otherwise
*/
template <>
bool ascending<SortMode::Bubbletonic>(size_t node, [[maybe_unused]] size_t depth) noexcept {
return (node % 2) == 0;
}
/*!
* 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
@@ -22,33 +35,76 @@
*
* @return True if we need ascending configuration, false otherwise
*/
bool ascending(size_t node, size_t depth) noexcept {
template <>
bool ascending<SortMode::Bitonic>(size_t node, size_t depth) noexcept {
return !(node & (1 << depth));
}
/*!
* Returns the node's partner for data exchange during the sorting network iterations
* of Bubbletonic
*
* @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));
template <>
size_t partner<SortMode::Bubbletonic>(size_t node, size_t step) noexcept {
// return (node % 2 == step % 2) ? node + 1 : node - 1;
return (((node+step) % 2) == 0) ? node + 1 : node - 1;
}
/*!
* Predicate to check if a node keeps the small numbers during the bitonic
* sort network exchange.
* Returns the node's partner for data exchange during the sorting network iterations
* of Bitonic
*
* @param node The current node
* @param step The step of the sorting network
* @return The node id of the partner for data exchange
*/
template <>
size_t partner<SortMode::Bitonic>(size_t node, size_t step) noexcept {
return (node ^ (1 << step));
}
/*!
* Predicate to check if a node keeps the small numbers during the bubbletonic sort network exchange.
*
* @param node The node for which we check
* @param partner The partner of the data exchange
* @return True if the node should keep the small values, false otherwise
*/
template <>
bool keepsmall<SortMode::Bubbletonic>(size_t node, size_t partner, [[maybe_unused]] size_t depth) noexcept {
assert(node != partner);
return (node < partner);
}
/*!
* 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 {
template <>
bool keepsmall<SortMode::Bitonic>(size_t node, size_t partner, size_t depth) noexcept {
assert(node != partner);
return ascending(node, depth) == (node < partner);
return ascending<SortMode::Bitonic>(node, depth) == (node < partner);
}
/*!
* Predicate to check if the node is active in the current iteration of the bubbletonic
* sort exchange.
*
* @param node The node to check
* @param nodes The total number of nodes
* @return True if the node is active, false otherwise
*/
bool isActive(size_t node, size_t nodes) noexcept {
return (node < nodes);
}
void exchange(size_t node, size_t partner) {
@@ -65,12 +121,57 @@ void minmax(AllData_t& data, size_t node, size_t partner, bool keepsmall) {
}
}
void sort_network(AllData_t& data, size_t nodes, size_t depth) {
void bubbletonic_network(AllData_t& data, size_t nodes, size_t depth) {
for (size_t node = 0 ; node < nodes ; ++node) { // Currently we do all nodes here!
auto part = partner<SortMode::Bubbletonic>(node, depth);
auto ks = keepsmall<SortMode::Bubbletonic>(node, part, 0);
if (isActive(node, nodes) && node < part) {
exchange(node, part);
minmax(data, node, part, ks);
// elbow-sort here
if (ascending<SortMode::Bubbletonic>(node, 0))
std::sort(data[node].begin(), data[node].end(), std::less<>());
else
std::sort(data[node].begin(), data[node].end(), std::greater<>());
if (ascending<SortMode::Bubbletonic>(part, 0))
std::sort(data[part].begin(), data[part].end(), std::less<>());
else
std::sort(data[part].begin(), data[part].end(), std::greater<>());
}
}
}
void distbubbletonic(size_t P, AllData_t& data) {
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<SortMode::Bubbletonic>(node, 0))
std::sort(data[node].begin(), data[node].end(), std::less<>());
else
std::sort(data[node].begin(), data[node].end(), std::greater<>());
}
for (size_t depth = 0; depth < P-1; ++depth) {
bubbletonic_network(data, P, depth);
}
// Invert the descending ones
for (size_t node = 0 ; node < P ; ++node) { // Currently we do all nodes here!
if (!ascending<SortMode::Bubbletonic>(node, 0))
std::sort(data[node].begin(), data[node].end(), std::less<>());
}
}
void bitonic_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);
for (size_t node = 0; node < nodes; ++node) { // Currently we do all nodes here!
auto part = partner<SortMode::Bitonic>(node, step);
auto ks = keepsmall<SortMode::Bitonic>(node, part, depth);
if (node < part) {
exchange(node, part);
minmax(data, node, part, ks);
@@ -84,7 +185,7 @@ void distbitonic(size_t P, AllData_t& data) {
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))
if (ascending<SortMode::Bitonic>(node, 0))
std::sort(data[node].begin(), data[node].end(), std::less<>());
else
std::sort(data[node].begin(), data[node].end(), std::greater<>());
@@ -92,11 +193,11 @@ void distbitonic(size_t P, AllData_t& data) {
// Run through sort network using elbow-sort
for (size_t depth = 1; depth <= p; ++depth) {
sort_network(data, P, depth);
bitonic_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))
if (ascending<SortMode::Bitonic>(node, depth))
std::sort(data[node].begin(), data[node].end(), std::less<>());
else
std::sort(data[node].begin(), data[node].end(), std::greater<>());