Skip to content

Commit

Permalink
added counting_sort to examples
Browse files Browse the repository at this point in the history
  • Loading branch information
gblelloch committed Feb 25, 2024
1 parent 2c59394 commit ef2a04e
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 7 deletions.
3 changes: 2 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ set(EXAMPLES "primes" "BFS" "word_counts" "tokens" "filter" "linefit"
"fast_fourier_transform" "bucketed_dijkstra" "push_relabel_max_flow"
"knuth_morris_pratt" "huffman_tree" "decision_tree_c45" "karatsuba" "suffix_tree"
"2d_linear_program" "box_kdtree" "radix_tree" "ray_trace" "hash_map" "oct_tree"
"3d_range" "rectangle_intersection" "star_connectivity" "ldd_connectivity" "boruvka")
"3d_range" "rectangle_intersection" "star_connectivity" "ldd_connectivity" "boruvka"
"counting_sort")

function(add_example NAME)
add_executable(${NAME} ${NAME}.cpp)
Expand Down
7 changes: 3 additions & 4 deletions examples/boruvka.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <parlay/sequence.h>
#include <parlay/delayed.h>
#include <parlay/utilities.h>
#include <parlay/internal/get_time.h>

#include "star_connectivity.h"

Expand All @@ -17,9 +16,9 @@ using edge = std::pair<vertex,vertex>;
using w_edge = std::pair<edge,w_type>;

parlay::sequence<w_type> boruvka(const parlay::sequence<w_edge>& E,
const parlay::sequence<vertex> V,
parlay::sequence<std::atomic<w_type>>& W,
parlay::sequence<vertex>& P) {
const parlay::sequence<vertex> V,
parlay::sequence<std::atomic<w_type>>& W,
parlay::sequence<vertex>& P) {
//std::cout << E.size() << ", " << V.size() << std::endl;

if (E.size() == 0) return parlay::sequence<w_type>();
Expand Down
48 changes: 48 additions & 0 deletions examples/counting_sort.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include <iostream>
#include <string>
#include <random>

#include <parlay/io.h>
#include <parlay/primitives.h>
#include <parlay/random.h>
#include <parlay/sequence.h>

#include "counting_sort.h"

// **************************************************************
// Driver
// **************************************************************
int main(int argc, char* argv[]) {
auto usage = "Usage: counting_sort <n>";
if (argc != 2) std::cout << usage << std::endl;
else {
long n;
try { n = std::stol(argv[1]); }
catch (...) { std::cout << usage << std::endl; return 1; }

long num_buckets = 256;
long num_partitions = std::min<long>(1000l, n / (256 * 16) + 1);

parlay::random_generator gen;
std::uniform_int_distribution<long> dis(0, num_buckets - 1);

// generate random long values
auto data = parlay::tabulate(n, [&] (long i) {
auto r = gen[i];
return dis(r);});

parlay::internal::timer t("Time");
parlay::sequence<long> result;
for (int i=0; i < 5; i++) {
result = data;
t.start();
result = counting_sort(data, data, num_buckets, num_partitions);
t.next("counting_sort");
}

auto first_ten = result.head(10);
auto last_ten = result.tail(10);
std::cout << "first 10 elements: " << parlay::to_chars(first_ten) << std::endl;
std::cout << "last 10 elements: " << parlay::to_chars(last_ten) << std::endl;
}
}
50 changes: 50 additions & 0 deletions examples/counting_sort.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <algorithm>
#include <functional>

#include <parlay/parallel.h>
#include <parlay/sequence.h>
#include <parlay/primitives.h>

template <typename T, typename Keys>
parlay::sequence<T> counting_sort(const parlay::sequence<T>& in, const Keys& keys,
long num_buckets, long num_parts) {
long n = in.size();
long part_size = (n - 1)/num_parts + 1;

auto all_counts = parlay::tabulate(num_parts, [&] (long i) {
long start = i * part_size;
long end = std::min<long>(start + part_size, n);
parlay::sequence<int> local_counts(num_buckets, 0);
for (size_t j = start; j < end; j++) local_counts[keys[j]]++;
return local_counts;}, 1);

// need to transpose the counts for the scan
auto counts = parlay::sequence<int>::uninitialized(num_buckets * num_parts);
parlay::parallel_for(0, num_buckets, [&] (long i) {
for (size_t j = 0; j < num_parts; j++)
counts[i* num_parts + j] = all_counts[j][i];}, 1);
all_counts.clear();

// scan for offsets for all buckets
parlay::scan_inplace(counts);

auto out = parlay::sequence<T>::uninitialized(n);

// go back over partitions to place in final location
parlay::parallel_for(0, num_parts, [&] (long i) {
long start = i * part_size;
long end = std::min<long>(start + part_size, n);
parlay::sequence<int> local_offsets(num_buckets, 0);

// transpose back
for (int j = 0; j < num_buckets; j++)
local_offsets[j] = counts[num_parts * j + i];

// copy to output
for (size_t j = start; j < end; j++) {
int k = local_offsets[keys[j]]++;
__builtin_prefetch (((char*) &out[k]) + 64);
out[k] = in[j];
}}, 1);
return out;
}
1 change: 0 additions & 1 deletion examples/ldd_connectivity.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <parlay/primitives.h>
#include <parlay/sequence.h>
#include <parlay/random.h>
#include <parlay/internal/get_time.h>

#include "low_diameter_decomposition.h"
#include "star_connectivity.h"
Expand Down
2 changes: 1 addition & 1 deletion examples/star_connectivity.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include <utility>
#include <random>
#include <optional>

#include <parlay/primitives.h>
#include <parlay/sequence.h>
#include <parlay/random.h>
#include <parlay/internal/get_time.h>

using rg = typename parlay::random_generator;
std::uniform_int_distribution<int> dis(0,1);
Expand Down

0 comments on commit ef2a04e

Please sign in to comment.