Skip to content

Commit efdfae9

Browse files
author
Samuel Pollard
committed
Started implementing Algorithm R and updated README
1 parent a152317 commit efdfae9

File tree

5 files changed

+82
-53
lines changed

5 files changed

+82
-53
lines changed

LICENSE.txt LICENSE

File renamed without changes.

README.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
1-
# Quantifying error for MPI Reduce
1+
# Quantifying Error for MPI Reduce
2+
3+
## Dependencies
4+
- [SimGrid](https://github.com/simgrid/simgrid) - preferably most recent git version. Also requires cmake
5+
6+
## Building
7+
- To build: `make`
8+
- To run quick test `make quick`
9+
- To run some experiments `make sim`. This outputs results in a tsv, with the
10+
exception of SimGrid diagnostics.
11+

assoc.cxx

+56-39
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,100 @@
1-
/* The t is for "Template" C++ file
1+
/* Implementation of random_reduction_tree template
22
*/
33

44
#include "assoc.hxx"
55
using namespace std;
66

7-
random_kary_tree::random_kary_tree() { };
8-
random_kary_tree::~random_kary_tree() { };
7+
random_reduction_tree::random_reduction_tree() { };
8+
random_reduction_tree::~random_reduction_tree() { };
99

10-
random_kary_tree::random_kary_tree(int k, long n, FLOAT_T* A) : k_(k), n_(n), A_(A)
10+
random_reduction_tree::random_reduction_tree(int k, long n, FLOAT_T* A)
11+
: k_(k), n_(n), A_(A)
1112
{
1213
typename tree<FLOAT_T>::iterator top, root;
1314
top = t.begin();
1415
root = t.insert(top, nan(""));
15-
if (k != 2) {
16+
irem = n-1; /* Inner nodes remaining */
17+
lrem = n; /* Leaf nodes remaining */
18+
changed_t v;
19+
if (k == 2) {
20+
// changed_t v = fill_balanced_binary_tree(irem, root, lrem);
21+
v = grow_random_binary_tree(root, lrem);
22+
} else {
1623
fprintf(stderr, "generic k-ary trees not supported yet (%d)\n", k);
17-
throw 3;
24+
throw TREE_ERROR;
1825
}
19-
irem = n-1;
20-
lrem = n;
21-
changed_t v = fill_balanced_binary_tree(irem, root, lrem);
22-
// changed_t v = fill_binary_tree(irem, root, lrem);
26+
2327
if (v.inner != irem || v.leaf != lrem) {
2428
fprintf(stderr, "Didn't fill tree correctly: (irem=%ld lrem=%ld, n=%ld)\n",
2529
v.inner, v.leaf, n_);
26-
throw 3;
30+
throw TREE_ERROR;
2731
}
2832
}
2933

30-
FLOAT_T random_kary_tree::sum_tree()
34+
FLOAT_T random_reduction_tree::sum_tree()
3135
{
3236
return 0.0/0.0;
3337
}
3438

35-
FLOAT_T random_kary_tree::multiply_tree()
39+
FLOAT_T random_reduction_tree::multiply_tree()
3640
{
3741
return 0.0/0.0;
3842
}
3943

40-
changed_t random_kary_tree::fill_balanced_binary_tree(
44+
/* Make a balanced binary tree. Not random */
45+
changed_t random_reduction_tree::fill_balanced_binary_tree(
4146
long irem, tree<FLOAT_T>::iterator current, long lrem)
4247
{
4348
return (changed_t) {.inner = 0, .leaf = 0};
4449
}
4550

46-
/* Helper, recursive function for fill_random_kary_tree */
47-
/* irem: The number of inner nodes remaining.
51+
/* Make a random binary tree. Algorithm R from The Art of Computer
52+
* Programming, Volume 4, pre-fascicle 4A: A Draft of Section 7.2.1.6:
53+
* Generating All Trees, Donald Knuth.
54+
* irem: The number of inner nodes remaining.
4855
* t: Current node of the tree
4956
* lrem: Number of leaves remaining to add
5057
* A: Array of values to place in the tree. Removed from the right.
5158
* returns: The number of inner nodes and leaf nodes added in the subtree
5259
*/
53-
changed_t random_kary_tree::fill_binary_tree(
54-
long irem, tree<FLOAT_T>::iterator current, long lrem)
60+
changed_t random_reduction_tree::grow_random_binary_tree(
61+
tree<FLOAT_T>::iterator root, long lrem)
5562
{
56-
int dir = 0;
57-
changed_t rv {.inner = 0, .leaf = 0};
58-
typename tree<FLOAT_T>::iterator l, r;
59-
/* To add another inner node we need at least 2 left in leaf budget */
60-
if (irem > 0 && lrem >= 2) {
61-
dir = rand() % 2;
62-
} else {
63-
dir = 0;
63+
if ((2 * lrem + 1) >= RAND_MAX) {
64+
fprintf(stderr, "tree too big\n");
65+
throw TREE_ERROR;
6466
}
65-
66-
if (dir == 0) { /* I'm a leaf */
67-
*current = A_[lrem - 1];
68-
rv.leaf++;
69-
} else { /* I'm an inner node */
70-
l = t.append_child(current, nan(""));
71-
r = t.append_child(current, nan(""));
72-
rv = fill_binary_tree(irem-1, l, lrem-1); // Save at least 1 leaf
73-
/* Subtract how much we filled on the left side */
74-
rv = fill_binary_tree((n_-1)-rv.inner, r, n_-rv.leaf);
67+
/* Allocate an array */
68+
long x, k, b, n, rem;
69+
long *L;
70+
L = (long *) malloc((2*lrem + 1)*sizeof(long));
71+
/* Initialize (R1) */
72+
n = 0;
73+
L[0] = 0;
74+
while (n < lrem) { /* Done? (R2) */
75+
/* Advance i (R3) */
76+
x = rand() % (4 * n + 1);
77+
n++;
78+
b = x % 2;
79+
k = x / 2;
80+
L[2*n - b] = 2*n;
81+
L[2*n - 1 + b] = L[k];
82+
L[k] = 2*n - 1;
83+
}
84+
/* Debug */
85+
printf("[%ld", L[0]);
86+
for (rem = 1; rem < 2 * lrem + 1; rem++) {
87+
printf(", %ld", L[rem]);
7588
}
76-
return rv;
89+
printf("]\n");
90+
91+
/* Now, to convert to C++ tree */
92+
free(L);
93+
return (changed_t) {.inner = 0, .leaf = 0};
7794
}
7895

7996
/* Explicit template instantiation. Here, we see two flavors, respectively:
8097
* classes and class member functions */
81-
/* template class random_kary_tree<double>; */
82-
/* template random_kary_tree<double>::random_kary_tree(int k, long n, double* A); */
98+
/* template class random_reduction_tree<double>; */
99+
/* template random_reduction_tree<double>::random_reduction_tree(int k, long n, double* A); */
83100

assoc.hxx

+10-8
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,33 @@
1616
#define FLOAT_T double
1717
#endif
1818

19+
#define TREE_ERROR 3
20+
1921
/* For recursive fill_binary_tree function */
2022
typedef struct chg {
2123
long inner;
2224
long leaf;
2325
} changed_t;
2426

25-
/* Look at C++ Concepts */
26-
class random_kary_tree {
27+
class random_reduction_tree {
2728
public:
28-
random_kary_tree(); // Empty constructor
29-
random_kary_tree(int k, long n, FLOAT_T* A); // Construct and randomize
30-
~random_kary_tree(); // Destructor
29+
random_reduction_tree(); // Empty constructor
30+
random_reduction_tree(int k, long n, FLOAT_T* A); // Construct and randomize
31+
~random_reduction_tree(); // Destructor
3132
FLOAT_T sum_tree(); // Add all leaves. Sum is at the root.
3233
FLOAT_T multiply_tree(); // Multiply all leaves. Product is at the root.
3334
changed_t fill_binary_tree(
34-
long irem, tree<FLOAT_T>::iterator current, long lrem);
35+
long irem, tree<FLOAT_T>::iterator current, long lrem);
3536
private:
37+
changed_t grow_random_binary_tree(
38+
tree<FLOAT_T>::iterator root, long lrem);
3639
changed_t fill_balanced_binary_tree(
37-
long irem, tree<FLOAT_T>::iterator current, long lrem);
40+
long irem, tree<FLOAT_T>::iterator current, long lrem);
3841
tree<FLOAT_T> t; // The tree
3942
int k_; // Fan-out of tree
4043
long n_; // Size of array of elements to insert
4144
FLOAT_T* A_; // Elements to put in the leaves
4245
long irem; // Inner nodes remaining
4346
long lrem; // Leaf nodes remaining
4447
};
45-
4648
#endif

dotprod_mpi.cxx

+5-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* + omp_dotprod_mpi.c - MPI only version
1010
* - omp_dotprod_hybrid.c - Hybrid MPI and OpenMP version
1111
* SOURCE: Blaise Barney
12-
* LAST REVISED: 5/18/20 - Samuel Pollard
12+
* LAST REVISED: 6/18/20 - Samuel Pollard
1313
******************************************************************************/
1414
#define USAGE "mpirun -np <N> ./dotprod_mpi <veclen> <topology>"
1515

@@ -45,7 +45,7 @@ int main (int argc, char* argv[])
4545
int taskid, numtasks;
4646
long i, j, chunk, len, rc=0;
4747
double *a, *b, *as, *bs, *rank_sum;
48-
double mysum, nc_sum, par_sum, can_mpi_sum; //, rassoc_sum;
48+
double mysum, nc_sum, par_sum, can_mpi_sum, rassoc_sum;
4949
double starttime, endtime, ptime;
5050
union udouble {
5151
double d;
@@ -139,7 +139,7 @@ int main (int argc, char* argv[])
139139
printf("numtasks\tveclen\ttopology\treduction algorithm\treduction order\tparallel time\tFP (decimal)\tFP (%%a)\tFP (hex)\n");
140140

141141
// Generate a random summation (TODO)
142-
// rassoc_sum = associative_sum_rand<double>(numtasks, rank_sum, 1);
142+
rassoc_sum = associative_sum_rand<double>(numtasks, rank_sum, 1);
143143
// pv.d = rassoc_sum;
144144
// printf("Random assocs: dot(x,y) =\t%a\t0x%lx\n", rassoc_sum, pv.u);
145145
pv.d = par_sum;
@@ -173,9 +173,9 @@ template <typename T>
173173
T associative_sum_rand(long n, T* A, int seed)
174174
{
175175
srand(seed);
176-
random_kary_tree t;
176+
random_reduction_tree t;
177177
try {
178-
t = random_kary_tree(2, n, A);
178+
t = random_reduction_tree(2, n, A);
179179
} catch (int e) {
180180
return 0.0/0.0;
181181
}

0 commit comments

Comments
 (0)