24 #ifndef GRAPHLAB_FAST_MULTINOMIAL_HPP
25 #define GRAPHLAB_FAST_MULTINOMIAL_HPP
31 #include <boost/integer.hpp>
32 #include <boost/random.hpp>
34 #include <graphlab.hpp>
36 #include <graphlab/parallel/pthread_tools.hpp>
37 #include <graphlab/parallel/atomic.hpp>
39 #include <graphlab/util/generics/float_selector.hpp>
42 #include <graphlab/macros_def.hpp>
50 class fast_multinomial {
52 typedef float_selector<sizeof(size_t)>::float_type float_t;
55 size_t first_leaf_index;
61 std::vector<float_t> tree;
64 atomic<size_t> num_support;
80 uint64_t next_powerof2(uint64_t val) {
82 val = val | (val >> 1);
83 val = val | (val >> 2);
84 val = val | (val >> 4);
85 val = val | (val >> 8);
86 val = val | (val >> 16);
87 val = val | (val >> 32);
95 size_t left_child(
size_t i)
const {
return 2 * i + 1; }
98 size_t right_child(
size_t i)
const {
return 2 * i + 2; }
101 size_t parent(
size_t i)
const {
return (i-1) / 2; }
104 size_t sibling(
size_t i)
const {
107 return i + (i & 1)*2 - 1;
111 size_t tree_loc_from_asg(
size_t asg)
const {
112 size_t loc = asg + first_leaf_index;
113 assert(loc < tree.size());
114 assert(is_leaf(loc));
119 size_t asg_from_tree_loc(
size_t i)
const {
121 size_t asg = i - first_leaf_index;
122 assert(asg < num_asg);
128 bool is_leaf(
size_t i)
const {
129 return i >= first_leaf_index;
134 bool is_root(
size_t i)
const {
return i == 0; }
139 bool try_sample(
size_t& asg,
size_t cpuid) {
141 while ( !is_leaf(loc) ) {
143 float_t left_p = tree.at(left_child(loc));
144 float_t right_p = tree.at(right_child(loc));
146 if (left_p + right_p == 0)
return false;
147 else if (right_p == 0) loc = left_child(loc);
148 else if (left_p == 0) loc = right_child(loc);
151 float_t childsum = left_p + right_p;
152 float_t rndnumber = graphlab::random::uniform<float_t>(0,1);
153 if((childsum * rndnumber) < left_p)
154 loc = left_child(loc);
156 loc = right_child(loc);
159 assert(is_leaf(loc));
160 asg = asg_from_tree_loc(loc);
161 assert(asg < num_asg);
167 void propagate_change(
size_t loc) {
170 for( ; !is_root(loc); loc = parent(loc) ) {
172 size_t sibling_loc = sibling(loc);
173 assert(sibling_loc < tree.size());
175 size_t parent_loc = parent(loc);
176 assert(parent_loc < tree.size());
178 assert(parent_loc == parent(sibling_loc));
181 volatile float_t* sibling1 = &(tree[loc]);
182 volatile float_t* sibling2 = &(tree[sibling_loc]);
183 volatile float_t* parent = &(tree[parent_loc]);
197 float_t sum = (*sibling1) + (*sibling2);
200 float_t sum2 = (*sibling1) + (*sibling2);
201 float_t parentval = (*parent);
202 if (sum2 == parentval)
break;
214 fast_multinomial(
size_t num_asg,
224 first_leaf_index = next_powerof2(num_asg) - 1;
225 size_t tree_size = first_leaf_index + next_powerof2(num_asg);
226 tree.resize(tree_size, 0.0);
229 void zero(
size_t asg) {
230 assert(asg < num_asg);
231 size_t loc = tree_loc_from_asg(asg);
233 float_t old_value = tree[loc];
234 float_t new_value = 0;
236 old_value = tree[loc];
238 propagate_change(loc);
245 void set(
size_t asg, float_t value) {
246 assert(asg < num_asg);
248 size_t loc = tree_loc_from_asg(asg);
250 float_t old_value = tree[loc];
251 float_t new_value = value;
253 old_value = tree[loc];
255 if(old_value == 0 && new_value > 0) {
258 propagate_change(loc);
260 if(old_value > 0 && new_value == 0) {
266 void add(
size_t asg, float_t value) {
267 assert(asg < num_asg);
269 size_t loc = tree_loc_from_asg(asg);
271 float_t old_value = tree[loc];
272 float_t new_value = value + old_value;
274 old_value = tree[loc];
275 new_value = value + old_value;
278 if(old_value == 0 && new_value > 0) {
281 propagate_change(loc);
285 void max(
size_t asg, float_t value) {
286 assert(asg < num_asg);
288 size_t loc = tree_loc_from_asg(asg);
290 float_t old_value = tree[loc];
291 float_t new_value = std::max(value, old_value);
293 old_value = tree[loc];
294 new_value = std::max(value, old_value);
296 if(old_value == 0 && new_value > 0) {
299 propagate_change(loc);
301 if(old_value > 0 && new_value == 0) {
310 bool sample(
size_t& ret_asg,
size_t cpuid) {
313 volatile float_t *root = &(tree[0]);
314 while(num_support.value > 0 || (*root) > 0) {
316 if(try_sample(ret_asg, cpuid)) {
317 assert(ret_asg < num_asg);
351 bool pop(
size_t& ret_asg,
size_t cpuid) {
352 if(tree.empty())
return false;
354 while(num_support.value > 0 || tree[0] > 0) {
356 if(try_sample(ret_asg, cpuid)) {
357 assert(ret_asg < num_asg);
361 size_t loc = tree_loc_from_asg(ret_asg);
363 float_t old_value = tree[loc];
364 float_t new_value = 0;
366 old_value = tree[loc];
373 propagate_change(loc);
381 std::cout <<
"Queue emptied!: " << tree[0]
382 <<
", " << num_support.value << std::endl;
388 size_t positive_support() {
389 return num_support.value;
394 for (
size_t i = 0; i < std::min(tree.size(), size_t(1000)); ++i) {
396 std::cout <<
"Leaf(" << asg_from_tree_loc(i)
397 <<
", [" << parent(i) <<
"], "
400 std::cout <<
"Node(" << i <<
", "
401 <<
"[" << left_child(i) <<
", "
402 << right_child(i) <<
"], "
406 std::cout << std::endl;
409 float_t get_weight(
size_t asg)
const {
410 size_t loc = tree_loc_from_asg(asg);
414 bool has_support(
size_t asg)
const {
415 size_t loc = tree_loc_from_asg(asg);
416 return tree[loc] > 0;
421 std::fill(tree.begin(), tree.end(), 0.0);
422 num_support.value = 0;
430 #include <graphlab/macros_undef.hpp>