HW2: A local version of distbubbletonic added
This commit is contained in:
+115
-14
@@ -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<>());
|
||||
|
||||
Reference in New Issue
Block a user