Skip to content

Commit

Permalink
Merge pull request #61 from DrMarkS/small_bitonic
Browse files Browse the repository at this point in the history
Small bitonic
  • Loading branch information
swenson authored Aug 20, 2019
2 parents 43163ef + f8cbd55 commit b00c2ce
Show file tree
Hide file tree
Showing 6 changed files with 758 additions and 20 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Copyright (c) 2012 Google Inc. All Rights Reserved.

CC ?= gcc
CFLAGS ?= -O3 -g -Wall -std=c89 -pedantic -Wno-long-long
CFLAGS ?= -O3 -g -Wall -std=c89 -pedantic -Wno-long-long -Wno-format

default: demo stresstest multidemo test

Expand All @@ -28,4 +28,4 @@ benchmark: benchmark.c sort.h
$(CC) $(CFLAGS) benchmark.c -o benchmark

format:
astyle --options=astyle.options sort.h demo.c multidemo.c stresstest.c benchmark.c
astyle --options=astyle.options sort.h bitonic_sort.h demo.c multidemo.c stresstest.c benchmark.c
4 changes: 4 additions & 0 deletions benchmark.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

#define SORT_NAME sorter
#define SORT_TYPE int64_t
#define MAX(x,y) (((x) > (y) ? (x) : (y)))
#define MIN(x,y) (((x) < (y) ? (x) : (y)))
#define SORT_CMP(x, y) ((x) - (y))
#define SORT_CSWAP(x, y) {SORT_TYPE _sort_swap_temp = MAX((x), (y)); (x) = MIN((x),(y)); (y) = _sort_swap_temp;}
#include "sort.h"

/* Used to control the stress test */
Expand Down Expand Up @@ -136,6 +139,7 @@ int main(void) {
TEST_STDLIB(mergesort);
#endif
TEST_SORT_H(binary_insertion_sort);
TEST_SORT_H(bitonic_sort);
TEST_SORT_H(quick_sort);
TEST_SORT_H(merge_sort);
TEST_SORT_H(heap_sort);
Expand Down
29 changes: 23 additions & 6 deletions demo.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
but the one below is often faster for integer types.
*/
#define SORT_CMP(x, y) (x - y)
#define MAX(x,y) (((x) > (y) ? (x) : (y)))
#define MIN(x,y) (((x) < (y) ? (x) : (y)))
#define SORT_CSWAP(x, y) {SORT_TYPE _sort_swap_temp = MAX((x), (y)); (x) = MIN((x),(y)); (y) = _sort_swap_temp;}
#include "sort.h"

/*
Expand Down Expand Up @@ -40,11 +43,11 @@ void verify(int64_t *dst, const int size) {
for (i = 1; i < size; i++) {
if (dst[i - 1] > dst[i]) {
printf("Verify failed! at %d\n", i);

for (i = i - 2; i < SIZE; i++) {
printf(" %lld", (long long) dst[i]);
}

/*
for (i = i - 2; i < SIZE; i++) {
printf(" %lld", (long long) dst[i]);
}
*/
printf("\n");
break;
}
Expand Down Expand Up @@ -155,7 +158,7 @@ void run_tests(void) {
printf("selection sort time: %10.2f us per iteration\n", total_time / RUNS);
srand48(SEED);
total_time = 0.0;

for (i = 0; i < RUNS; i++) {
fill(arr, SIZE);
memcpy(dst, arr, sizeof(int64_t) * SIZE);
Expand All @@ -170,6 +173,20 @@ void run_tests(void) {
srand48(SEED);
total_time = 0.0;

for (i = 0; i < RUNS; i++) {
fill(arr, SIZE);
memcpy(dst, arr, sizeof(int64_t) * SIZE);
start_time = utime();
sorter_bitonic_sort(dst, SIZE);
end_time = utime();
total_time += end_time - start_time;
verify(dst, SIZE);
}

printf("bitonic sort time: %10.2f us per iteration\n", total_time / RUNS);
srand48(SEED);
total_time = 0.0;

for (i = 0; i < RUNS; i++) {
fill(arr, SIZE);
memcpy(dst, arr, sizeof(int64_t) * SIZE);
Expand Down
148 changes: 148 additions & 0 deletions generate_bitonic_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import requests

max_small_sort = 16
small_sort_only = True

def generate_small_sort(n, rev=False):
s = "http://jgamble.ripco.net/cgi-bin/nw.cgi?inputs=%d&algorithm=best&output=svg" % n
ret = requests.get(s)
content = ret.text
lines = [l for l in content.split('\n') if l.startswith('[[')]
swps = ""
for _l in lines:
l = _l[1:-1]
ll = l.split(']')
for _t in ll:
if '[' not in _t:
continue
t = _t.split('[')[-1]
i, j = t.split(',')
if not rev:
swps += "\tSORT_CSWAP(dst[%s], dst[%s]);\n" % (i, j)
else:
swps += "\tSORT_CSWAP(dst[%s], dst[%s]);\n" % (j, i)
swps += '\n'
if not rev:
f = """
#define BITONIC_SORT_%d SORT_MAKE_STR(bitonic_sort_%d)
static __inline void BITONIC_SORT_%d(SORT_TYPE *dst) {
%s}
""" % (n, n, n, swps[:-1])
else:
f = """
#define BITONIC_SORT_REVERSE_%d SORT_MAKE_STR(bitonic_sort_reverse_%d)
static __inline void BITONIC_SORT_REVERSE_%d(SORT_TYPE *dst) {
%s}
""" % (n, n, n, swps[:-1])
return f


bitonic_sort_str = """
#ifndef SORT_CSWAP
#define SORT_CSWAP(x, y) { if(SORT_CMP((x),(y)) > 0) {SORT_SWAP((x),(y));}}
#endif
"""
bitonic_sort_str += "\n".join(generate_small_sort(i) for i in range(2,max_small_sort+1))

if small_sort_only:
bitonic_sort_case = "\n".join(" case %d:\n BITONIC_SORT_%d(dst);\n break;" % (n, n) for n in range(2, max_small_sort+1))
bitonic_sort_str += """
void BITONIC_SORT(SORT_TYPE *dst, const size_t size) {
switch(size) {
case 0:
case 1:
break;
%s
default:
BINARY_INSERTION_SORT(dst, size);
}
}
""" % (bitonic_sort_case)
print(bitonic_sort_str)
exit()



bitonic_sort_str += "\n".join(generate_small_sort(i, rev=True) for i in range(2,max_small_sort+1))

bitonic_sort_case = "\n".join(" case %d:\n BITONIC_SORT_%d(dst);\n break;" % (n, n) for n in range(2, max_small_sort+1))
bitonic_sort_case_rev = "\n".join(" case %d:\n BITONIC_SORT_REVERSE_%d(dst);\n break;" % (n, n) for n in range(2, max_small_sort+1))

bitonic_sort_str += """
#define BITONIC_SORT SORT_MAKE_STR(bitonic_sort)
void BITONIC_SORT(SORT_TYPE *dst, const size_t size);
#define BITONIC_SORT_REVERSE SORT_MAKE_STR(bitonic_sort_reverse)
void BITONIC_SORT_REVERSE(SORT_TYPE *dst, const size_t size);
"""

bitonic_sort_str += """
#define BITONIC_MERGE SORT_MAKE_STR(bitonic_merge)
void BITONIC_MERGE(SORT_TYPE *dst, const size_t size) {
size_t m, i, j;
if (size <= 1) {
return;
}
m = 1ULL<<(63 - CLZ(size-1));
j = m;
for (i = 0; i < size - m; ++i, ++j) {
SORT_CSWAP(dst[i], dst[j]);
}
BITONIC_MERGE(dst, m);
BITONIC_MERGE(dst + m, size - m);
}
#define BITONIC_MERGE_REVERSE SORT_MAKE_STR(bitonic_merge_reverse)
void BITONIC_MERGE_REVERSE(SORT_TYPE *dst, const size_t size) {
size_t m, i, j;
if (size <= 1) {
return;
}
m = 1ULL<<(63 - CLZ(size-1));
j = m;
for (i = 0; i < size - m; ++i, ++j) {
SORT_CSWAP(dst[j], dst[i]);
}
BITONIC_MERGE_REVERSE(dst, m);
BITONIC_MERGE_REVERSE(dst + m, size - m);
}
"""

bitonic_sort_str += """
void BITONIC_SORT(SORT_TYPE *dst, const size_t size) {
switch(size) {
case 0:
case 1:
break;
%s
default:
/*printf("Bitonic sort size = %%ld", size);*/
BITONIC_SORT_REVERSE(dst, (size>>1));
BITONIC_SORT(dst + (size>>1), size - (size>>1));
BITONIC_MERGE(dst, size);
}
}
""" % (bitonic_sort_case)

bitonic_sort_str += """
void BITONIC_SORT_REVERSE(SORT_TYPE *dst, const size_t size) {
switch(size) {
case 0:
case 1:
break;
%s
default:
/*printf("Bitonic sort reverse size = %%ld", size);*/
BITONIC_SORT(dst, (size>>1));
BITONIC_SORT_REVERSE(dst + (size>>1), size - (size>>1));
BITONIC_MERGE_REVERSE(dst, size);
}
}
""" % (bitonic_sort_case_rev)

import os

with open('bitonic_sort.h', 'w') as F:
F.write(bitonic_sort_str)

os.system('astyle --options=astyle.options bitonic_sort.h')
Loading

0 comments on commit b00c2ce

Please sign in to comment.