2 A Java implementation of the bisort Olden benchmark.
3 The Olden benchmark implements a Bitonic Sort as described in:
5 G. Bilardi and A. Nicolau, "Adaptive Bitonic Sorting: An optimal parallel
6 algorithm for shared-memory machines." SIAM J. Comput. 18(2):216-228, 1998.
8 The benchmarks sorts N numbers where N is a power of 2. If the user provides
9 an input value that is not a power of 2, then we use the nearest power of
10 2 value that is less than the input value.
12 Converted to D and obtimized by leonardo maffi, V.1.0, Oct 31 2009.
14 Removed output unless an option is passed by Leandro Lucarella, 2010-08-04.
15 Downloaded from http://www.fantascienza.net/leonardo/js/
16 http://www.fantascienza.net/leonardo/js/dolden_bisort.zip
20 import tango.stdc.stdio: printf, fprintf, stderr;
21 import tango.stdc.stdlib: exit;
22 import Integer = tango.text.convert.Integer;
23 alias Integer.parse toInt;
24 import tango.stdc.time: CLOCKS_PER_SEC, clock;
26 import std.c.stdio: printf, fprintf, stderr;
27 import std.c.stdlib: exit;
28 import std.conv: toInt;
29 import std.c.time: CLOCKS_PER_SEC, clock;
34 return clock() / cast(float)CLOCKS_PER_SEC;
39 * A class that represents a value to be sorted by the <tt>BiSort</tt>
40 * algorithm. We represents a values as a node in a binary tree.
44 private Value left, right;
46 const bool FORWARD = false;
47 const bool BACKWARD = true;
49 // These are used by the Olden benchmark random no. generator
50 private const int CONST_m1 = 10000;
51 private const int CONST_b = 31415821;
52 const int RANGE = 100;
55 * Constructor for a node representing a value in the bitonic sort tree.
56 * @param v the integer value which is the sort key
65 * Create a random tree of value to be sorted using the bitonic sorting algorithm.
67 * @param size the number of values to create.
68 * @param seed a random number generator seed value
69 * @return the root of the (sub) tree.
71 static Value createTree(int size, int seed) {
74 int next_val = seed % RANGE;
76 Value retval = new Value(next_val);
77 retval.left = createTree(size/2, seed);
78 retval.right = createTree(size/2, skiprand(seed, size+1));
87 * Perform a bitonic sort based upon the Bilardi and Nicolau algorithm.
89 * @param spr_val the "spare" value in the algorithm.
90 * @param direction the direction of the sort (forward or backward)
91 * @return the new "spare" value.
93 int bisort(int spr_val, bool direction) {
95 if ((value > spr_val) ^ direction) {
102 value = left.bisort(val, direction);
103 bool ndir = !direction;
104 spr_val = right.bisort(spr_val, ndir);
105 spr_val = bimerge(spr_val, direction);
112 * Perform the merge part of the bitonic sort. The merge part does
113 * the actualy sorting.
114 * @param spr_val the "spare" value in the algorithm.
115 * @param direction the direction of the sort (forward or backward)
116 * @return the new "spare" value
118 int bimerge(int spr_val, bool direction) {
123 bool rightexchange = (rv > spr_val) ^ direction;
129 while (pl !is null) {
132 Value plr = pl.right;
135 Value prr = pr.right;
137 bool elementexchange = (lv > rv) ^ direction;
139 if (elementexchange) {
148 if (elementexchange) {
160 value = left.bimerge(value, direction);
161 spr_val = right.bimerge(spr_val, direction);
168 * Swap the values and the right subtrees.
169 * @param n the other subtree involved in the swap.
171 void swapValRight(Value n) {
173 Value tmpr = n.right;
184 * Swap the values and the left subtrees.
185 * @param n the other subtree involved in the swap.
187 void swapValLeft(Value n) {
200 * Print out the nodes in the binary tree in infix order.
205 printf("%d\n", value);
212 * A random generator. The original Olden benchmark uses its
213 * own random generator. We use the same one in the Java version.
214 * @return the next random number in the sequence.
216 private static int mult(int p, int q) {
217 int p1 = p / CONST_m1;
218 int p0 = p % CONST_m1;
219 int q1 = q / CONST_m1;
220 int q0 = q % CONST_m1;
221 return ((p0 * q1 + p1 * q0) % CONST_m1) * CONST_m1 + p0 * q0;
226 * A routine to skip the next <i>n</i> random numbers.
227 * @param seed the current random no. seed
228 * @param n the number of numbers to skip
230 private static int skiprand(int seed, int n) {
238 * Return a random number based upon the seed value.
239 * @param seed the random number seed value
240 * @return a random number based upon the seed value.
242 static int random(int seed) {
243 int tmp = mult(seed, CONST_b) + 1;
249 final public class BiSort {
250 private static int size = 0; // The number of values to sort.
251 private static bool printMsgs = false; // Print information messages
252 private static bool printResults = false; // Print the tree after each step
256 * The main routine which creates a tree and sorts it a couple of times.
257 * @param args the command line arguments
259 public static final void main(char[][] args) {
263 printf("Bisort with %d values\n", nextPow2(size+1) - 1);
265 auto start2 = myclock();
266 Value tree = Value.createTree(size, 12345768);
267 auto end2 = myclock();
268 int sval = Value.random(245867) % Value.RANGE;
272 printf("%d\n", sval);
276 printf("Beginning bitonic sort\n");
278 auto start0 = myclock();
279 sval = tree.bisort(sval, Value.FORWARD);
280 auto end0 = myclock();
284 printf("%d\n", sval);
287 auto start1 = myclock();
288 sval = tree.bisort(sval, Value.BACKWARD);
289 auto end1 = myclock();
293 printf("%d\n", sval);
297 printf("Creation time: %f\n", end2 - start2);
298 printf("Time to sort forward = %f\n", end0 - start0);
299 printf("Time to sort backward = %f\n", end1 - start1);
300 printf("Total: %f\n", end1 - start0);
307 * Parse the command line options.
308 * @param args the command line options.
310 private static final void parseCmdLine(char[][] args) {
314 while (i < args.length && args[i][0] == '-') {
317 // check for options that require arguments
319 if (i < args.length) {
320 size = toInt(args[i++]);
322 throw new Exception("-l requires the number of levels");
324 } else if (arg == "-m") {
326 } else if (arg == "-p") {
328 } else if (arg == "-h") {
338 * The usage routine which describes the program options.
340 private static final void usage() {
341 fprintf(stderr, "usage: bisort_d -s <size> [-p] [-i] [-h]\n");
342 fprintf(stderr, " -s the number of values to sort\n");
343 fprintf(stderr, " -m (print informative messages)\n");
344 fprintf(stderr, " -p (print the binary tree after each step)\n");
345 fprintf(stderr, " -h (print this message)\n");
350 private static /*unsigned*/ int nextPow2(/*unsigned*/ int x) {
352 throw new Exception("x must be >= 0");
364 void main(char[][] args) {