Vowpal Wabbit
Classes | Functions | Variables
stagewise_poly.cc File Reference
#include <float.h>
#include <cassert>
#include "gd.h"
#include "accumulate.h"
#include "reductions.h"
#include "vw.h"
#include "vw_allreduce.h"

Go to the source code of this file.

Classes

struct  sort_data
 
struct  stagewise_poly
 

Functions

uint64_t stride_shift (const stagewise_poly &poly, uint64_t idx)
 
uint64_t stride_un_shift (const stagewise_poly &poly, uint64_t idx)
 
uint64_t do_ft_offset (const stagewise_poly &poly, uint64_t idx)
 
uint64_t un_ft_offset (const stagewise_poly &poly, uint64_t idx)
 
uint64_t wid_mask (const stagewise_poly &poly, uint64_t wid)
 
uint64_t wid_mask_un_shifted (const stagewise_poly &poly, uint64_t wid)
 
uint64_t constant_feat (const stagewise_poly &poly)
 
uint64_t constant_feat_masked (const stagewise_poly &poly)
 
size_t depthsbits_sizeof (const stagewise_poly &poly)
 
void depthsbits_create (stagewise_poly &poly)
 
bool parent_get (const stagewise_poly &poly, uint64_t wid)
 
void parent_toggle (stagewise_poly &poly, uint64_t wid)
 
bool cycle_get (const stagewise_poly &poly, uint64_t wid)
 
void cycle_toggle (stagewise_poly &poly, uint64_t wid)
 
uint8_t min_depths_get (const stagewise_poly &poly, uint64_t wid)
 
void min_depths_set (stagewise_poly &poly, uint64_t wid, uint8_t depth)
 
void sanity_check_state (stagewise_poly &poly)
 
uint64_t child_wid (const stagewise_poly &poly, uint64_t wi_atomic, uint64_t wi_general)
 
void sort_data_create (stagewise_poly &poly)
 
void sort_data_ensure_sz (stagewise_poly &poly, size_t len)
 
int sort_data_compar_heap (sort_data &a_v, sort_data &b_v)
 
void sort_data_update_support (stagewise_poly &poly)
 
void synthetic_reset (stagewise_poly &poly, example &ec)
 
void synthetic_decycle (stagewise_poly &poly)
 
void synthetic_create_rec (stagewise_poly &poly, float v, uint64_t findex)
 
void synthetic_create (stagewise_poly &poly, example &ec, bool training)
 
void predict (stagewise_poly &poly, single_learner &base, example &ec)
 
void learn (stagewise_poly &poly, single_learner &base, example &ec)
 
void reduce_min (uint8_t &v1, const uint8_t &v2)
 
void reduce_min_max (uint8_t &v1, const uint8_t &v2)
 
void end_pass (stagewise_poly &poly)
 
void finish_example (vw &all, stagewise_poly &poly, example &ec)
 
void save_load (stagewise_poly &poly, io_buf &model_file, bool read, bool text)
 
base_learnerstagewise_poly_setup (options_i &options, vw &all)
 

Variables

static constexpr uint32_t parent_bit = 1
 
static constexpr uint32_t cycle_bit = 2
 
static constexpr uint32_t tree_atomics = 134
 
static constexpr float tolerance = 1e-9f
 
static constexpr uint32_t indicator_bit = 128
 
static constexpr uint32_t default_depth = 127
 

Function Documentation

◆ child_wid()

uint64_t child_wid ( const stagewise_poly poly,
uint64_t  wi_atomic,
uint64_t  wi_general 
)
inline

Definition at line 205 of file stagewise_poly.cc.

References constant_feat_masked(), stride_shift(), stride_un_shift(), and wid_mask().

Referenced by synthetic_create_rec().

206 {
207  assert(wi_atomic == wid_mask(poly, wi_atomic));
208  assert(wi_general == wid_mask(poly, wi_general));
209  assert((wi_atomic & (stride_shift(poly, 1) - 1)) == 0);
210  assert((wi_general & (stride_shift(poly, 1) - 1)) == 0);
211 
212  if (wi_atomic == constant_feat_masked(poly))
213  return wi_general;
214  else if (wi_general == constant_feat_masked(poly))
215  return wi_atomic;
216  else
217  {
218  // This is basically the "Fowler–Noll–Vo" hash. Ideally, the hash would be invariant
219  // to the monomial, whereas this here is sensitive to the path followed, but whatever.
220  // the two main big differences with FNV are: (1) the "*constant" case should also have
221  // a big prime (so the default hash shouldn't be identity on small things, and (2) the
222  // size should not just be a power of 2, but some big prime.
223  return wid_mask(
224  poly, stride_shift(poly, stride_un_shift(poly, wi_atomic) ^ (16777619 * stride_un_shift(poly, wi_general))));
225  }
226 }
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
uint64_t wid_mask(const stagewise_poly &poly, uint64_t wid)
uint64_t stride_un_shift(const stagewise_poly &poly, uint64_t idx)
uint64_t constant_feat_masked(const stagewise_poly &poly)

◆ constant_feat()

uint64_t constant_feat ( const stagewise_poly poly)
inline

Definition at line 120 of file stagewise_poly.cc.

References stagewise_poly::all, constant, stride_shift(), and vw::wpp.

Referenced by constant_feat_masked().

120 { return stride_shift(poly, constant * poly.all->wpp); }
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
constexpr uint64_t constant
Definition: constant.h:11
uint32_t wpp
Definition: global_data.h:432

◆ constant_feat_masked()

uint64_t constant_feat_masked ( const stagewise_poly poly)
inline

Definition at line 122 of file stagewise_poly.cc.

References constant_feat(), and wid_mask().

Referenced by child_wid(), sort_data_update_support(), and synthetic_create().

122 { return wid_mask(poly, constant_feat(poly)); }
uint64_t wid_mask(const stagewise_poly &poly, uint64_t wid)
uint64_t constant_feat(const stagewise_poly &poly)

◆ cycle_get()

bool cycle_get ( const stagewise_poly poly,
uint64_t  wid 
)
inline

Definition at line 150 of file stagewise_poly.cc.

References cycle_bit, stagewise_poly::depthsbits, stride_shift(), and wid_mask_un_shifted().

Referenced by sanity_check_state(), synthetic_create_rec(), and synthetic_decycle().

151 {
152  // note: intentionally leaving out ft_offset.
153  assert(wid % stride_shift(poly, 1) == 0);
154  if ((poly.depthsbits[wid_mask_un_shifted(poly, wid) * 2 + 1] & cycle_bit) > 0)
155  return true;
156  else
157  return false;
158 }
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
uint8_t * depthsbits
static constexpr uint32_t cycle_bit
uint64_t wid_mask_un_shifted(const stagewise_poly &poly, uint64_t wid)

◆ cycle_toggle()

void cycle_toggle ( stagewise_poly poly,
uint64_t  wid 
)
inline

Definition at line 160 of file stagewise_poly.cc.

References cycle_bit, stagewise_poly::depthsbits, stride_shift(), and wid_mask_un_shifted().

Referenced by synthetic_create_rec(), and synthetic_decycle().

161 {
162  // note: intentionally leaving out ft_offset.
163  assert(wid % stride_shift(poly, 1) == 0);
164  poly.depthsbits[wid_mask_un_shifted(poly, wid) * 2 + 1] ^= cycle_bit;
165 }
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
uint8_t * depthsbits
static constexpr uint32_t cycle_bit
uint64_t wid_mask_un_shifted(const stagewise_poly &poly, uint64_t wid)

◆ depthsbits_create()

void depthsbits_create ( stagewise_poly poly)

Definition at line 126 of file stagewise_poly.cc.

References stagewise_poly::all, default_depth, stagewise_poly::depthsbits, indicator_bit, and vw::length().

Referenced by stagewise_poly_setup().

127 {
128  poly.depthsbits = calloc_or_throw<uint8_t>(2 * poly.all->length());
129  for (uint64_t i = 0; i < poly.all->length() * 2; i += 2)
130  {
131  poly.depthsbits[i] = default_depth;
132  poly.depthsbits[i + 1] = indicator_bit;
133  }
134 }
size_t length()
Definition: global_data.h:513
uint8_t * depthsbits
static constexpr uint32_t default_depth
static constexpr uint32_t indicator_bit

◆ depthsbits_sizeof()

size_t depthsbits_sizeof ( const stagewise_poly poly)
inline

Definition at line 124 of file stagewise_poly.cc.

References stagewise_poly::all, and vw::length().

Referenced by end_pass(), and save_load().

124 { return (2 * poly.all->length() * sizeof(uint8_t)); }
size_t length()
Definition: global_data.h:513

◆ do_ft_offset()

uint64_t do_ft_offset ( const stagewise_poly poly,
uint64_t  idx 
)
inline

Definition at line 91 of file stagewise_poly.cc.

References example_predict::ft_offset, stagewise_poly::original_ec, and stagewise_poly::synth_ec.

Referenced by min_depths_get(), min_depths_set(), parent_get(), and parent_toggle().

92 {
93  // std::cout << poly.synth_ec.ft_offset << " " << poly.original_ec->ft_offset << std::endl;
94  assert(!poly.original_ec || poly.synth_ec.ft_offset == poly.original_ec->ft_offset);
95  return idx + poly.synth_ec.ft_offset;
96 }
example * original_ec

◆ end_pass()

void end_pass ( stagewise_poly poly)

Definition at line 581 of file stagewise_poly.cc.

References accumulate_scalar(), stagewise_poly::all, vw::all_reduce, stagewise_poly::batch_sz, stagewise_poly::depthsbits, depthsbits_sizeof(), stagewise_poly::num_examples, stagewise_poly::num_examples_sync, stagewise_poly::numpasses, vw::numpasses, sanity_check_state(), stagewise_poly::sum_input_sparsity, stagewise_poly::sum_input_sparsity_sync, stagewise_poly::sum_sparsity, stagewise_poly::sum_sparsity_sync, and stagewise_poly::update_support.

582 {
583  if (!!poly.batch_sz || (poly.all->all_reduce != nullptr && poly.numpasses > 1))
584  return;
585 
586  uint64_t sum_sparsity_inc = poly.sum_sparsity - poly.sum_sparsity_sync;
587  uint64_t sum_input_sparsity_inc = poly.sum_input_sparsity - poly.sum_input_sparsity_sync;
588  uint64_t num_examples_inc = poly.num_examples - poly.num_examples_sync;
589 
590 #ifdef DEBUG
591  std::cout << "Sanity before allreduce\n";
592  sanity_check_state(poly);
593 #endif // DEBUG
594 
595  vw &all = *poly.all;
596  if (all.all_reduce != nullptr)
597  {
598  /*
599  * The following is inconsistent with the transplant code in
600  * synthetic_create_rec(), which clears parent bits on depth mismatches.
601  * But it's unclear what the right behavior is in general for either
602  * case...
603  */
604  all_reduce<uint8_t, reduce_min_max>(all, poly.depthsbits, depthsbits_sizeof(poly));
605 
606  sum_input_sparsity_inc = (uint64_t)accumulate_scalar(all, (float)sum_input_sparsity_inc);
607  sum_sparsity_inc = (uint64_t)accumulate_scalar(all, (float)sum_sparsity_inc);
608  num_examples_inc = (uint64_t)accumulate_scalar(all, (float)num_examples_inc);
609  }
610 
611  poly.sum_input_sparsity_sync = poly.sum_input_sparsity_sync + sum_input_sparsity_inc;
613  poly.sum_sparsity_sync = poly.sum_sparsity_sync + sum_sparsity_inc;
614  poly.sum_sparsity = poly.sum_sparsity_sync;
615  poly.num_examples_sync = poly.num_examples_sync + num_examples_inc;
616  poly.num_examples = poly.num_examples_sync;
617 
618 #ifdef DEBUG
619  std::cout << "Sanity after allreduce\n";
620  sanity_check_state(poly);
621 #endif // DEBUG
622 
623  if (poly.numpasses != poly.all->numpasses)
624  {
625  poly.update_support = true;
626  poly.numpasses++;
627  }
628 }
void sanity_check_state(stagewise_poly &poly)
uint64_t num_examples
size_t depthsbits_sizeof(const stagewise_poly &poly)
uint8_t * depthsbits
uint64_t sum_input_sparsity
uint64_t sum_input_sparsity_sync
uint64_t sum_sparsity_sync
AllReduce * all_reduce
Definition: global_data.h:381
uint64_t num_examples_sync
size_t numpasses
Definition: global_data.h:451
uint64_t sum_sparsity
float accumulate_scalar(vw &all, float local_sum)
Definition: accumulate.cc:44

◆ finish_example()

void finish_example ( vw all,
stagewise_poly poly,
example ec 
)

Definition at line 630 of file stagewise_poly.cc.

References VW::finish_example(), example::num_features, output_and_account_example(), and stagewise_poly::synth_ec.

Referenced by stagewise_poly_setup().

631 {
632  size_t temp_num_features = ec.num_features;
635  ec.num_features = temp_num_features;
636  VW::finish_example(all, ec);
637 }
void output_and_account_example(vw &all, active &a, example &ec)
Definition: active.cc:105
size_t num_features
Definition: example.h:67
void finish_example(vw &, example &)
Definition: parser.cc:881

◆ learn()

void learn ( stagewise_poly poly,
single_learner base,
example ec 
)

Definition at line 506 of file stagewise_poly.cc.

References stagewise_poly::all, vw::all_reduce, stagewise_poly::batch_sz, stagewise_poly::batch_sz_double, example::example_counter, example::l, label_data::label, stagewise_poly::last_example_counter, LEARNER::learner< T, E >::learn(), stagewise_poly::next_batch_sz, stagewise_poly::numpasses, stagewise_poly::original_ec, example::partial_prediction, example::pred, predict(), polyprediction::scalar, polylabel::simple, sort_data_update_support(), stagewise_poly::synth_ec, synthetic_create(), vw::training, stagewise_poly::update_support, and example::updated_prediction.

Referenced by stagewise_poly_setup().

507 {
508  bool training = poly.all->training && ec.l.simple.label != FLT_MAX;
509  poly.original_ec = &ec;
510 
511  if (training)
512  {
513  if (poly.update_support)
514  {
516  poly.update_support = false;
517  }
518 
519  synthetic_create(poly, ec, training);
520  base.learn(poly.synth_ec);
523  ec.pred.scalar = poly.synth_ec.pred.scalar;
524 
525  if (ec.example_counter
526  // following line is to avoid repeats when multiple reductions on same example.
527  // XXX ideally, would get all "copies" of an example before scheduling the support
528  // update, but how do we know?
529  && poly.last_example_counter != ec.example_counter && poly.batch_sz &&
530  ((poly.batch_sz_double && !(ec.example_counter % poly.next_batch_sz)) ||
531  (!poly.batch_sz_double && !(ec.example_counter % poly.batch_sz))))
532  {
533  poly.next_batch_sz *= 2; // no effect when !poly.batch_sz_double
534  poly.update_support = (poly.all->all_reduce == nullptr || poly.numpasses == 1);
535  }
537  }
538  else
539  predict(poly, base, ec);
540 }
size_t example_counter
Definition: example.h:64
void synthetic_create(stagewise_poly &poly, example &ec, bool training)
float scalar
Definition: example.h:45
void sort_data_update_support(stagewise_poly &poly)
float partial_prediction
Definition: example.h:68
float label
Definition: simple_label.h:14
float updated_prediction
Definition: example.h:69
label_data simple
Definition: example.h:28
uint32_t next_batch_sz
bool training
Definition: global_data.h:488
uint64_t last_example_counter
AllReduce * all_reduce
Definition: global_data.h:381
example * original_ec
polylabel l
Definition: example.h:57
polyprediction pred
Definition: example.h:60
void learn(E &ec, size_t i=0)
Definition: learner.h:160
void predict(stagewise_poly &poly, single_learner &base, example &ec)

◆ min_depths_get()

uint8_t min_depths_get ( const stagewise_poly poly,
uint64_t  wid 
)
inline

Definition at line 167 of file stagewise_poly.cc.

References stagewise_poly::depthsbits, do_ft_offset(), stride_shift(), and stride_un_shift().

Referenced by sanity_check_state(), and synthetic_create_rec().

168 {
169  assert(wid % stride_shift(poly, 1) == 0);
170  assert(do_ft_offset(poly, wid) % stride_shift(poly, 1) == 0);
171  return poly.depthsbits[stride_un_shift(poly, do_ft_offset(poly, wid)) * 2];
172 }
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
uint64_t do_ft_offset(const stagewise_poly &poly, uint64_t idx)
uint8_t * depthsbits
uint64_t stride_un_shift(const stagewise_poly &poly, uint64_t idx)

◆ min_depths_set()

void min_depths_set ( stagewise_poly poly,
uint64_t  wid,
uint8_t  depth 
)
inline

Definition at line 174 of file stagewise_poly.cc.

References stagewise_poly::depthsbits, do_ft_offset(), stride_shift(), and stride_un_shift().

Referenced by synthetic_create_rec().

175 {
176  assert(wid % stride_shift(poly, 1) == 0);
177  assert(do_ft_offset(poly, wid) % stride_shift(poly, 1) == 0);
178  poly.depthsbits[stride_un_shift(poly, do_ft_offset(poly, wid)) * 2] = depth;
179 }
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
uint64_t do_ft_offset(const stagewise_poly &poly, uint64_t idx)
uint8_t * depthsbits
uint64_t stride_un_shift(const stagewise_poly &poly, uint64_t idx)

◆ parent_get()

bool parent_get ( const stagewise_poly poly,
uint64_t  wid 
)
inline

Definition at line 136 of file stagewise_poly.cc.

References stagewise_poly::depthsbits, do_ft_offset(), parent_bit, stride_shift(), and wid_mask_un_shifted().

Referenced by sanity_check_state(), sort_data_update_support(), and synthetic_create_rec().

137 {
138  assert(wid % stride_shift(poly, 1) == 0);
139  assert(do_ft_offset(poly, wid) % stride_shift(poly, 1) == 0);
140  return poly.depthsbits[wid_mask_un_shifted(poly, do_ft_offset(poly, wid)) * 2 + 1] & parent_bit;
141 }
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
uint64_t do_ft_offset(const stagewise_poly &poly, uint64_t idx)
uint8_t * depthsbits
static constexpr uint32_t parent_bit
uint64_t wid_mask_un_shifted(const stagewise_poly &poly, uint64_t wid)

◆ parent_toggle()

void parent_toggle ( stagewise_poly poly,
uint64_t  wid 
)
inline

Definition at line 143 of file stagewise_poly.cc.

References stagewise_poly::depthsbits, do_ft_offset(), parent_bit, stride_shift(), and wid_mask_un_shifted().

Referenced by sort_data_update_support(), and synthetic_create_rec().

144 {
145  assert(wid % stride_shift(poly, 1) == 0);
146  assert(do_ft_offset(poly, wid) % stride_shift(poly, 1) == 0);
147  poly.depthsbits[wid_mask_un_shifted(poly, do_ft_offset(poly, wid)) * 2 + 1] ^= parent_bit;
148 }
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
uint64_t do_ft_offset(const stagewise_poly &poly, uint64_t idx)
uint8_t * depthsbits
static constexpr uint32_t parent_bit
uint64_t wid_mask_un_shifted(const stagewise_poly &poly, uint64_t wid)

◆ predict()

void predict ( stagewise_poly poly,
single_learner base,
example ec 
)

Definition at line 496 of file stagewise_poly.cc.

References stagewise_poly::original_ec, example::partial_prediction, example::pred, LEARNER::learner< T, E >::predict(), polyprediction::scalar, stagewise_poly::synth_ec, synthetic_create(), and example::updated_prediction.

Referenced by learn(), and stagewise_poly_setup().

497 {
498  poly.original_ec = &ec;
499  synthetic_create(poly, ec, false);
500  base.predict(poly.synth_ec);
503  ec.pred.scalar = poly.synth_ec.pred.scalar;
504 }
void synthetic_create(stagewise_poly &poly, example &ec, bool training)
void predict(E &ec, size_t i=0)
Definition: learner.h:169
float scalar
Definition: example.h:45
float partial_prediction
Definition: example.h:68
float updated_prediction
Definition: example.h:69
example * original_ec
polyprediction pred
Definition: example.h:60

◆ reduce_min()

void reduce_min ( uint8_t &  v1,
const uint8_t &  v2 
)

Definition at line 542 of file stagewise_poly.cc.

References default_depth.

543 {
544  if (v1 == default_depth)
545  v1 = v2;
546  else if (v2 != default_depth)
547  v1 = (v1 <= v2) ? v1 : v2;
548 }
static constexpr uint32_t default_depth

◆ reduce_min_max()

void reduce_min_max ( uint8_t &  v1,
const uint8_t &  v2 
)

Definition at line 550 of file stagewise_poly.cc.

References default_depth, and indicator_bit.

551 {
552  bool parent_or_depth;
553  if (v1 & indicator_bit)
554  parent_or_depth = true;
555  else
556  parent_or_depth = false;
557  bool p_or_d2;
558  if (v2 & indicator_bit)
559  p_or_d2 = true;
560  else
561  p_or_d2 = false;
562  if (parent_or_depth != p_or_d2)
563  {
564 #ifdef DEBUG
565  std::cout << "Reducing parent with depth!!!!!";
566 #endif // DEBUG
567  return;
568  }
569 
570  if (parent_or_depth)
571  v1 = (v1 >= v2) ? v1 : v2;
572  else
573  {
574  if (v1 == default_depth)
575  v1 = v2;
576  else if (v2 != default_depth)
577  v1 = (v1 <= v2) ? v1 : v2;
578  }
579 }
static constexpr uint32_t default_depth
static constexpr uint32_t indicator_bit

◆ sanity_check_state()

void sanity_check_state ( stagewise_poly poly)

Definition at line 182 of file stagewise_poly.cc.

References stagewise_poly::all, cycle_bit, cycle_get(), default_depth, parameters::dense_weights, stagewise_poly::depthsbits, indicator_bit, vw::length(), min_depths_get(), parent_bit, parent_get(), parameters::sparse, parameters::sparse_weights, stride_shift(), vw::weights, and wid_mask_un_shifted().

Referenced by end_pass(), and sort_data_update_support().

183 {
184  for (uint64_t i = 0; i != poly.all->length(); ++i)
185  {
186  uint64_t wid = stride_shift(poly, i);
187 
188  assert(!cycle_get(poly, wid));
189 
190  assert(!(min_depths_get(poly, wid) == default_depth && parent_get(poly, wid)));
191 
192  if (poly.all->weights.sparse)
193  assert(!(min_depths_get(poly, wid) == default_depth && fabsf(poly.all->weights.sparse_weights[wid]) > 0));
194  else
195  assert(!(min_depths_get(poly, wid) == default_depth && fabsf(poly.all->weights.dense_weights[wid]) > 0));
196  // assert( min_depths_get(poly, wid) != default_depth && fabsf(poly.all->weights[wid]) < tolerance );
197 
198  assert(!(poly.depthsbits[wid_mask_un_shifted(poly, wid) * 2 + 1] & ~(parent_bit + cycle_bit + indicator_bit)));
199  }
200 }
size_t length()
Definition: global_data.h:513
parameters weights
Definition: global_data.h:537
bool parent_get(const stagewise_poly &poly, uint64_t wid)
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
uint8_t min_depths_get(const stagewise_poly &poly, uint64_t wid)
bool cycle_get(const stagewise_poly &poly, uint64_t wid)
uint8_t * depthsbits
static constexpr uint32_t cycle_bit
static constexpr uint32_t parent_bit
static constexpr uint32_t default_depth
dense_parameters dense_weights
static constexpr uint32_t indicator_bit
sparse_parameters sparse_weights
uint64_t wid_mask_un_shifted(const stagewise_poly &poly, uint64_t wid)

◆ save_load()

void save_load ( stagewise_poly poly,
io_buf model_file,
bool  read,
bool  text 
)

Definition at line 639 of file stagewise_poly.cc.

References bin_text_read_write_fixed(), stagewise_poly::depthsbits, depthsbits_sizeof(), io_buf::files, and v_array< T >::size().

Referenced by stagewise_poly_setup().

640 {
641  if (model_file.files.size() > 0)
642  {
643  std::stringstream msg;
645  model_file, (char *)poly.depthsbits, (uint32_t)depthsbits_sizeof(poly), "", read, msg, text);
646  }
647  // unfortunately, following can't go here since save_load called before gd::save_load and thus
648  // weight vector state uninitialiazed.
649  //#ifdef DEBUG
650  // std::cout << "Sanity check after save_load... " << flush;
651  // sanity_check_state(poly);
652  // std::cout << "done" << std::endl;
653  //#endif //DEBUG
654 }
size_t depthsbits_sizeof(const stagewise_poly &poly)
uint8_t * depthsbits
size_t size() const
Definition: v_array.h:68
v_array< int > files
Definition: io_buf.h:64
size_t bin_text_read_write_fixed(io_buf &io, char *data, size_t len, const char *read_message, bool read, std::stringstream &msg, bool text)
Definition: io_buf.h:326

◆ sort_data_compar_heap()

int sort_data_compar_heap ( sort_data a_v,
sort_data b_v 
)

Definition at line 259 of file stagewise_poly.cc.

References sort_data::weightsal.

Referenced by sort_data_update_support().

259 { return (a_v.weightsal > b_v.weightsal); }
float weightsal

◆ sort_data_create()

void sort_data_create ( stagewise_poly poly)

Definition at line 228 of file stagewise_poly.cc.

References stagewise_poly::sd, and stagewise_poly::sd_len.

Referenced by stagewise_poly_setup().

229 {
230  poly.sd = nullptr;
231  poly.sd_len = 0;
232 }
sort_data * sd

◆ sort_data_ensure_sz()

void sort_data_ensure_sz ( stagewise_poly poly,
size_t  len 
)

Definition at line 234 of file stagewise_poly.cc.

References stagewise_poly::all, vw::length(), stagewise_poly::sd, and stagewise_poly::sd_len.

Referenced by sort_data_update_support().

235 {
236  if (poly.sd_len < len)
237  {
238  size_t len_candidate = 2 * len;
239 #ifdef DEBUG
240  std::cout << "resizing sort buffer; current size " << poly.sd_len;
241 #endif // DEBUG
242  poly.sd_len = (len_candidate > poly.all->length()) ? poly.all->length() : len_candidate;
243 #ifdef DEBUG
244  std::cout << ", new size " << poly.sd_len << std::endl;
245 #endif // DEBUG
246  free(poly.sd); // okay for null.
247  poly.sd = calloc_or_throw<sort_data>(poly.sd_len);
248  }
249  assert(len <= poly.sd_len);
250 }
size_t length()
Definition: global_data.h:513
sort_data * sd

◆ sort_data_update_support()

void sort_data_update_support ( stagewise_poly poly)

Definition at line 274 of file stagewise_poly.cc.

References stagewise_poly::all, constant_feat_masked(), example_predict::ft_offset, vw::length(), vw::normalized_idx, stagewise_poly::num_examples, stagewise_poly::original_ec, parent_get(), parent_toggle(), sanity_check_state(), stagewise_poly::sched_exponent, stagewise_poly::sd, stagewise_poly::sd_len, sort_data_compar_heap(), sort_data_ensure_sz(), stride_shift(), stagewise_poly::sum_input_sparsity, stagewise_poly::synth_ec, tolerance, vw::weights, sort_data::weightsal, and sort_data::wid.

Referenced by learn().

275 {
276  assert(poly.num_examples);
277 
278  // ft_offset affects parent_set / parent_get. This state must be reset at end.
279  uint64_t pop_ft_offset = poly.original_ec->ft_offset;
280  poly.synth_ec.ft_offset = 0;
281  assert(poly.original_ec);
282  poly.original_ec->ft_offset = 0;
283 
284  size_t num_new_features = (size_t)pow(poly.sum_input_sparsity * 1.0f / poly.num_examples, poly.sched_exponent);
285  num_new_features = (num_new_features > poly.all->length()) ? (uint64_t)poly.all->length() : num_new_features;
286  sort_data_ensure_sz(poly, num_new_features);
287 
288  sort_data *heap_end = poly.sd;
289  std::make_heap(poly.sd, heap_end, sort_data_compar_heap); // redundant
290  for (uint64_t i = 0; i != poly.all->length(); ++i)
291  {
292  uint64_t wid = stride_shift(poly, i);
293  if (!parent_get(poly, wid) && wid != constant_feat_masked(poly))
294  {
295  float weightsal = (fabsf(poly.all->weights[wid]) * poly.all->weights[poly.all->normalized_idx + (wid)]);
296  /*
297  * here's some depth penalization code. It was found to not improve
298  * statistical performance, and meanwhile it is verified as giving
299  * a nontrivial computational hit, thus commented out.
300  *
301  * - poly.magic_argument
302  * sqrtf(min_depths_get(poly, stride_shift(poly, i)) * 1.0 / poly.num_examples)
303  */
304  ;
305  if (weightsal > tolerance)
306  {
307  assert(heap_end >= poly.sd);
308  assert(heap_end <= poly.sd + num_new_features);
309 
310  if (heap_end - poly.sd == (int)num_new_features && poly.sd->weightsal < weightsal)
311  {
312  std::pop_heap(poly.sd, heap_end, sort_data_compar_heap);
313  --heap_end;
314  }
315 
316  assert(heap_end >= poly.sd);
317  assert(heap_end < poly.sd + poly.sd_len);
318 
319  if (heap_end - poly.sd < (int)num_new_features)
320  {
321  heap_end->weightsal = weightsal;
322  heap_end->wid = wid;
323  ++heap_end;
324  std::push_heap(poly.sd, heap_end, sort_data_compar_heap);
325  }
326  }
327  }
328  }
329  num_new_features = (uint64_t)(heap_end - poly.sd);
330 
331 #ifdef DEBUG
332  // eyeballing weights a pain if unsorted.
333  qsort(poly.sd, num_new_features, sizeof(sort_data), sort_data_compar);
334 #endif // DEBUG
335 
336  for (uint64_t pos = 0; pos < num_new_features && pos < poly.sd_len; ++pos)
337  {
338  assert(!parent_get(poly, poly.sd[pos].wid) && poly.sd[pos].weightsal > tolerance &&
339  poly.sd[pos].wid != constant_feat_masked(poly));
340  parent_toggle(poly, poly.sd[pos].wid);
341 #ifdef DEBUG
342  std::cout << "Adding feature " << pos << "/" << num_new_features << " || wid " << poly.sd[pos].wid
343  << " || sort value " << poly.sd[pos].weightsal << std::endl;
344 #endif // DEBUG
345  }
346 
347 #ifdef DEBUG
348  std::cout << "depths:";
349  for (uint64_t depth = 0; depth <= poly.max_depth && depth < sizeof(poly.depths) / sizeof(*poly.depths); ++depth)
350  std::cout << " [" << depth << "] = " << poly.depths[depth];
351  std::cout << std::endl;
352 
353  std::cout << "Sanity check after sort... " << flush;
354  sanity_check_state(poly);
355  std::cout << "done" << std::endl;
356 #endif // DEBUG
357 
358  // it's okay that these may have been initially unequal; synth_ec value irrelevant so far.
359  poly.original_ec->ft_offset = pop_ft_offset;
360  poly.synth_ec.ft_offset = pop_ft_offset;
361 }
void sanity_check_state(stagewise_poly &poly)
size_t length()
Definition: global_data.h:513
parameters weights
Definition: global_data.h:537
sort_data * sd
bool parent_get(const stagewise_poly &poly, uint64_t wid)
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
size_t normalized_idx
Definition: global_data.h:506
uint64_t num_examples
int sort_data_compar_heap(sort_data &a_v, sort_data &b_v)
uint64_t sum_input_sparsity
static constexpr float tolerance
void parent_toggle(stagewise_poly &poly, uint64_t wid)
example * original_ec
float weightsal
uint64_t wid
uint64_t constant_feat_masked(const stagewise_poly &poly)
void sort_data_ensure_sz(stagewise_poly &poly, size_t len)

◆ stagewise_poly_setup()

base_learner* stagewise_poly_setup ( options_i options,
vw all 
)

Definition at line 656 of file stagewise_poly.cc.

References VW::config::option_group_definition::add(), add(), VW::config::options_i::add_and_parse(), LEARNER::as_singleline(), depthsbits_create(), LEARNER::end_pass(), finish_example(), LEARNER::init_learner(), learn(), LEARNER::make_base(), VW::config::make_option(), predict(), save_load(), LEARNER::learner< T, E >::set_end_pass(), LEARNER::learner< T, E >::set_finish_example(), LEARNER::learner< T, E >::set_save_load(), setup_base(), and sort_data_create().

Referenced by parse_reductions().

657 {
658  auto poly = scoped_calloc_or_throw<stagewise_poly>();
659  bool stage_poly = false;
660  option_group_definition new_options("Stagewise polynomial options");
661  new_options.add(make_option("stage_poly", stage_poly).keep().help("use stagewise polynomial feature learning"))
662  .add(make_option("sched_exponent", poly->sched_exponent)
663  .default_value(1.f)
664  .help("exponent controlling quantity of included features"))
665  .add(make_option("batch_sz", poly->batch_sz)
666  .default_value(1000)
667  .help("multiplier on batch size before including more features"))
668  .add(make_option("batch_sz_no_doubling", poly->batch_sz_double).help("batch_sz does not double"));
669 #ifdef MAGIC_ARGUMENT
670  new_options.add(
671  make_typed_option("magic_argument", poly->magic_argument).default_value(0.).help("magical feature flag"));
672 #endif // MAGIC_ARGUMENT
673  options.add_and_parse(new_options);
674 
675  if (!stage_poly)
676  return nullptr;
677 
678  poly->all = &all;
679  depthsbits_create(*poly.get());
680  sort_data_create(*poly.get());
681 
682  poly->batch_sz_double = !poly->batch_sz_double;
683 
684  poly->sum_sparsity = 0;
685  poly->sum_input_sparsity = 0;
686  poly->num_examples = 0;
687  poly->sum_sparsity_sync = 0;
688  poly->sum_input_sparsity_sync = 0;
689  poly->num_examples_sync = 0;
690  poly->last_example_counter = -1;
691  poly->numpasses = 1;
692  poly->update_support = false;
693  poly->original_ec = nullptr;
694  poly->next_batch_sz = poly->batch_sz;
695 
700 
701  return make_base(l);
702 }
void finish_example(vw &all, stagewise_poly &poly, example &ec)
void sort_data_create(stagewise_poly &poly)
base_learner * make_base(learner< T, E > &base)
Definition: learner.h:462
virtual void add_and_parse(const option_group_definition &group)=0
void set_save_load(void(*sl)(T &, io_buf &, bool, bool))
Definition: learner.h:257
single_learner * as_singleline(learner< T, E > *l)
Definition: learner.h:476
void set_finish_example(void(*f)(vw &all, T &, E &))
Definition: learner.h:307
learner< T, E > & init_learner(free_ptr< T > &dat, L *base, void(*learn)(T &, L &, E &), void(*predict)(T &, L &, E &), size_t ws, prediction_type::prediction_type_t pred_type)
Definition: learner.h:369
void save_load(stagewise_poly &poly, io_buf &model_file, bool read, bool text)
int add(svm_params &params, svm_example *fec)
Definition: kernel_svm.cc:546
typed_option< T > make_option(std::string name, T &location)
Definition: options.h:80
void set_end_pass(void(*f)(T &))
Definition: learner.h:286
LEARNER::base_learner * setup_base(options_i &options, vw &all)
Definition: parse_args.cc:1222
void depthsbits_create(stagewise_poly &poly)
void end_pass(stagewise_poly &poly)
void learn(stagewise_poly &poly, single_learner &base, example &ec)
void predict(stagewise_poly &poly, single_learner &base, example &ec)

◆ stride_shift()

uint64_t stride_shift ( const stagewise_poly poly,
uint64_t  idx 
)
inline

◆ stride_un_shift()

uint64_t stride_un_shift ( const stagewise_poly poly,
uint64_t  idx 
)
inline

Definition at line 86 of file stagewise_poly.cc.

References stagewise_poly::all, parameters::stride_shift(), and vw::weights.

Referenced by child_wid(), min_depths_get(), min_depths_set(), and wid_mask_un_shifted().

87 {
88  return idx >> poly.all->weights.stride_shift();
89 }
parameters weights
Definition: global_data.h:537
uint32_t stride_shift()

◆ synthetic_create()

void synthetic_create ( stagewise_poly poly,
example ec,
bool  training 
)

Definition at line 470 of file stagewise_poly.cc.

References stagewise_poly::all, constant_feat_masked(), stagewise_poly::cur_depth, example_predict::feature_space, stagewise_poly::num_examples, example::num_features, stagewise_poly::original_ec, stagewise_poly::sum_input_sparsity, stagewise_poly::sum_sparsity, stagewise_poly::synth_ec, stagewise_poly::synth_rec_f, synthetic_decycle(), synthetic_reset(), example::total_sum_feat_sq, stagewise_poly::training, tree_atomics, feature::weight_index, and feature::x.

Referenced by learn(), and predict().

471 {
472  synthetic_reset(poly, ec);
473 
474  poly.cur_depth = 0;
475 
476  poly.synth_rec_f.x = 1.0;
477  poly.synth_rec_f.weight_index = constant_feat_masked(poly); // note: not ft_offset'd
478  poly.training = training;
479  /*
480  * Another choice is to mark the constant feature as the single initial
481  * parent, and recurse just on that feature (which arguably correctly interprets poly.cur_depth).
482  * Problem with this is if there is a collision with the root...
483  */
484  GD::foreach_feature<stagewise_poly, uint64_t, synthetic_create_rec>(*poly.all, *poly.original_ec, poly);
485  synthetic_decycle(poly);
487 
488  if (training)
489  {
490  poly.sum_sparsity += poly.synth_ec.num_features;
491  poly.sum_input_sparsity += ec.num_features;
492  poly.num_examples += 1;
493  }
494 }
float x
Definition: feature_group.h:27
uint64_t num_examples
uint64_t sum_input_sparsity
uint64_t weight_index
Definition: feature_group.h:28
static constexpr uint32_t tree_atomics
std::array< features, NUM_NAMESPACES > feature_space
size_t num_features
Definition: example.h:67
example * original_ec
void synthetic_reset(stagewise_poly &poly, example &ec)
uint64_t sum_sparsity
float total_sum_feat_sq
Definition: example.h:71
uint64_t constant_feat_masked(const stagewise_poly &poly)
void synthetic_decycle(stagewise_poly &poly)
uint32_t cur_depth

◆ synthetic_create_rec()

void synthetic_create_rec ( stagewise_poly poly,
float  v,
uint64_t  findex 
)

Definition at line 415 of file stagewise_poly.cc.

References stagewise_poly::all, child_wid(), stagewise_poly::cur_depth, cycle_get(), cycle_toggle(), default_depth, example_predict::feature_space, min_depths_get(), min_depths_set(), example::num_features, stagewise_poly::original_ec, parent_get(), parent_toggle(), stride_shift(), stagewise_poly::synth_ec, stagewise_poly::synth_rec_f, stagewise_poly::training, tree_atomics, un_ft_offset(), feature::weight_index, wid_mask(), and feature::x.

416 {
417  // Note: need to un_ft_shift since gd::foreach_feature bakes in the offset.
418  uint64_t wid_atomic = wid_mask(poly, un_ft_offset(poly, findex));
419  uint64_t wid_cur = child_wid(poly, wid_atomic, poly.synth_rec_f.weight_index);
420  assert(wid_atomic % stride_shift(poly, 1) == 0);
421 
422  // Note: only mutate learner state when in training mode. This is because
423  // the average test errors across multiple data sets should be equal to
424  // the test error on the merged dataset (which is violated if the code
425  // below is run at training time).
426  if (poly.cur_depth < min_depths_get(poly, wid_cur) && poly.training)
427  {
428  if (parent_get(poly, wid_cur))
429  {
430 #ifdef DEBUG
431  std::cout << "FOUND A TRANSPLANT!!! moving [" << wid_cur << "] from depth "
432  << (uint64_t)min_depths_get(poly, wid_cur) << " to depth " << poly.cur_depth << std::endl;
433 #endif // DEBUG
434  // XXX arguably, should also fear transplants that occured with
435  // a different ft_offset ; e.g., need to look out for cross-reduction
436  // collisions. Have not played with this issue yet...
437  parent_toggle(poly, wid_cur);
438  }
439  min_depths_set(poly, wid_cur, poly.cur_depth);
440  }
441 
442  if (!cycle_get(poly, wid_cur) &&
443  ((poly.cur_depth > default_depth ? default_depth : poly.cur_depth) == min_depths_get(poly, wid_cur)))
444  {
445  cycle_toggle(poly, wid_cur);
446 
447 #ifdef DEBUG
448  ++poly.depths[poly.cur_depth];
449 #endif // DEBUG
450 
451  feature temp = {v * poly.synth_rec_f.x, wid_cur};
452  poly.synth_ec.feature_space[tree_atomics].push_back(temp.x, temp.weight_index);
453  poly.synth_ec.num_features++;
454 
455  if (parent_get(poly, temp.weight_index))
456  {
457  feature parent_f = poly.synth_rec_f;
458  poly.synth_rec_f = temp;
459  ++poly.cur_depth;
460 #ifdef DEBUG
461  poly.max_depth = (poly.max_depth > poly.cur_depth) ? poly.max_depth : poly.cur_depth;
462 #endif // DEBUG
463  GD::foreach_feature<stagewise_poly, uint64_t, synthetic_create_rec>(*(poly.all), *(poly.original_ec), poly);
464  --poly.cur_depth;
465  poly.synth_rec_f = parent_f;
466  }
467  }
468 }
bool parent_get(const stagewise_poly &poly, uint64_t wid)
uint64_t stride_shift(const stagewise_poly &poly, uint64_t idx)
float x
Definition: feature_group.h:27
uint64_t wid_mask(const stagewise_poly &poly, uint64_t wid)
uint8_t min_depths_get(const stagewise_poly &poly, uint64_t wid)
bool cycle_get(const stagewise_poly &poly, uint64_t wid)
uint64_t child_wid(const stagewise_poly &poly, uint64_t wi_atomic, uint64_t wi_general)
uint64_t un_ft_offset(const stagewise_poly &poly, uint64_t idx)
uint64_t weight_index
Definition: feature_group.h:28
static constexpr uint32_t tree_atomics
std::array< features, NUM_NAMESPACES > feature_space
size_t num_features
Definition: example.h:67
static constexpr uint32_t default_depth
void parent_toggle(stagewise_poly &poly, uint64_t wid)
example * original_ec
void min_depths_set(stagewise_poly &poly, uint64_t wid, uint8_t depth)
uint32_t cur_depth
void cycle_toggle(stagewise_poly &poly, uint64_t wid)

◆ synthetic_decycle()

void synthetic_decycle ( stagewise_poly poly)

Definition at line 405 of file stagewise_poly.cc.

References cycle_get(), cycle_toggle(), example_predict::feature_space, features::indicies, features::size(), stagewise_poly::synth_ec, and tree_atomics.

Referenced by synthetic_create().

406 {
408  for (size_t i = 0; i < fs.size(); ++i)
409  {
410  assert(cycle_get(poly, fs.indicies[i]));
411  cycle_toggle(poly, fs.indicies[i]);
412  }
413 }
v_array< feature_index > indicies
the core definition of a set of features.
bool cycle_get(const stagewise_poly &poly, uint64_t wid)
static constexpr uint32_t tree_atomics
std::array< features, NUM_NAMESPACES > feature_space
size_t size() const
void cycle_toggle(stagewise_poly &poly, uint64_t wid)

◆ synthetic_reset()

void synthetic_reset ( stagewise_poly poly,
example ec 
)

Some comments on ft_offset.

The plan is to do the feature mapping dfs with weight indices ignoring the ft_offset. This is because ft_offset is then added at the end, guaranteeing local/strided access on synth_ec. This might not matter too much in this implementation (where, e.g., –oaa runs one after the other, not interleaved), but who knows.

(The other choice is to basically ignore adjusting for ft_offset when doing the traversal, which means synth_ec.ft_offset is 0 here...)

Anyway, so here is how ft_offset matters:

  • synthetic_create_rec must "normalize it out" of the fed weight value
  • parent and min_depths set/get are adjusted for it.
  • cycle set/get are not adjusted for it, since it doesn't matter for them.
  • operations on the whole weight vector (sorting, save_load, all_reduce) ignore ft_offset, just treat the thing as a flat vector.

Definition at line 363 of file stagewise_poly.cc.

References stagewise_poly::all, example::end_pass, example::example_counter, example_predict::feature_space, example_predict::ft_offset, example::in_use, example_predict::indices, example_predict::interactions, vw::interactions, example::l, example::num_features, v_array< T >::push_back(), v_array< T >::size(), example::sorted, stagewise_poly::synth_ec, example::tag, example::test_only, example::total_sum_feat_sq, tree_atomics, and example::weight.

Referenced by synthetic_create().

364 {
365  poly.synth_ec.l = ec.l;
366  poly.synth_ec.weight = ec.weight;
367  poly.synth_ec.tag = ec.tag;
369  poly.synth_ec.interactions = &poly.all->interactions;
370 
390  poly.synth_ec.ft_offset = ec.ft_offset;
391 
392  poly.synth_ec.test_only = ec.test_only;
393  poly.synth_ec.end_pass = ec.end_pass;
394  poly.synth_ec.sorted = ec.sorted;
395  poly.synth_ec.in_use = ec.in_use;
396 
397  poly.synth_ec.feature_space[tree_atomics].clear();
398  poly.synth_ec.num_features = 0;
399  poly.synth_ec.total_sum_feat_sq = 0;
400 
401  if (poly.synth_ec.indices.size() == 0)
403 }
v_array< char > tag
Definition: example.h:63
v_array< namespace_index > indices
size_t example_counter
Definition: example.h:64
std::vector< std::string > * interactions
bool sorted
Definition: example.h:78
size_t size() const
Definition: v_array.h:68
static constexpr uint32_t tree_atomics
std::array< features, NUM_NAMESPACES > feature_space
void push_back(const T &new_ele)
Definition: v_array.h:107
size_t num_features
Definition: example.h:67
polylabel l
Definition: example.h:57
bool in_use
Definition: example.h:79
float total_sum_feat_sq
Definition: example.h:71
std::vector< std::string > interactions
Definition: global_data.h:457
float weight
Definition: example.h:62
bool end_pass
Definition: example.h:77
bool test_only
Definition: example.h:76

◆ un_ft_offset()

uint64_t un_ft_offset ( const stagewise_poly poly,
uint64_t  idx 
)
inline

Definition at line 98 of file stagewise_poly.cc.

References stagewise_poly::all, example_predict::ft_offset, vw::length(), stagewise_poly::original_ec, parameters::stride_shift(), stagewise_poly::synth_ec, and vw::weights.

Referenced by synthetic_create_rec().

99 {
100  assert(!poly.original_ec || poly.synth_ec.ft_offset == poly.original_ec->ft_offset);
101  if (poly.synth_ec.ft_offset == 0)
102  return idx;
103  else
104  {
105  while (idx < poly.synth_ec.ft_offset)
106  {
107  idx += poly.all->length() << poly.all->weights.stride_shift();
108  }
109  return idx - poly.synth_ec.ft_offset;
110  }
111 }
size_t length()
Definition: global_data.h:513
parameters weights
Definition: global_data.h:537
example * original_ec
uint32_t stride_shift()

◆ wid_mask()

uint64_t wid_mask ( const stagewise_poly poly,
uint64_t  wid 
)
inline

Definition at line 113 of file stagewise_poly.cc.

References stagewise_poly::all, parameters::mask(), and vw::weights.

Referenced by child_wid(), constant_feat_masked(), and synthetic_create_rec().

113 { return wid & poly.all->weights.mask(); }
parameters weights
Definition: global_data.h:537
uint64_t mask()

◆ wid_mask_un_shifted()

uint64_t wid_mask_un_shifted ( const stagewise_poly poly,
uint64_t  wid 
)
inline

Definition at line 115 of file stagewise_poly.cc.

References stagewise_poly::all, parameters::mask(), stride_un_shift(), and vw::weights.

Referenced by cycle_get(), cycle_toggle(), parent_get(), parent_toggle(), and sanity_check_state().

116 {
117  return stride_un_shift(poly, wid & poly.all->weights.mask());
118 }
parameters weights
Definition: global_data.h:537
uint64_t stride_un_shift(const stagewise_poly &poly, uint64_t idx)
uint64_t mask()

Variable Documentation

◆ cycle_bit

constexpr uint32_t cycle_bit = 2
static

Definition at line 16 of file stagewise_poly.cc.

Referenced by cycle_get(), cycle_toggle(), and sanity_check_state().

◆ default_depth

constexpr uint32_t default_depth = 127
static

◆ indicator_bit

constexpr uint32_t indicator_bit = 128
static

Definition at line 19 of file stagewise_poly.cc.

Referenced by depthsbits_create(), reduce_min_max(), and sanity_check_state().

◆ parent_bit

constexpr uint32_t parent_bit = 1
static

Definition at line 15 of file stagewise_poly.cc.

Referenced by parent_get(), parent_toggle(), and sanity_check_state().

◆ tolerance

constexpr float tolerance = 1e-9f
static

Definition at line 18 of file stagewise_poly.cc.

Referenced by sort_data_update_support().

◆ tree_atomics

constexpr uint32_t tree_atomics = 134
static