#if !defined(HIST_QUANT_BINS) || !defined(HIST_FLOAT_BINS) || !defined(REDUCE_THREADS) || !defined(SCAN_THREADS) || \
!defined(HIST_SIDE_LEFT) || !defined(HIST_SIDE_RIGHT)
#error "the backend defines the kernel capacities before common.h"
#endif
struct FillParams {
uint n;
uint value;
};
struct GradParams {
uint n;
uint has_weight;
float sigmoid;
uint pad;
};
struct StatsParams {
uint n;
uint pad0;
uint pad1;
uint pad2;
};
struct QuantParams {
uint n;
uint row_offset_lo;
uint row_offset_hi;
float inv_grad_scale;
float inv_hess_scale;
int grad_max_q;
int hess_max_q;
uint constant_hessian;
uint stochastic;
uint seed;
uint iteration;
uint pad;
};
struct BagParams {
uint n;
uint chunk;
uint row_offset_lo;
uint row_offset_hi;
uint seed;
uint round;
uint threshold;
uint pad;
};
struct ScanParams {
uint n;
uint pad0;
uint pad1;
uint pad2;
};
struct PartitionParams {
uint begin;
uint count;
uint chunk;
uint row_stride;
uint group_base_lo;
uint group_base_hi;
uint column;
uint pad;
uint left_bins[8];
};
struct CopyParams {
uint begin;
uint count;
uint pad0;
uint pad1;
};
struct HistUnit {
uint words_base_lo;
uint words_base_hi;
uint row_words;
uint bin_begin;
uint num_bins;
uint cols_begin;
uint pad0;
uint pad1;
};
struct HistParams {
uint begin;
uint count;
uint rows_per_block;
uint side;
};
struct LeafSumParams {
float grad_scale;
float hess_scale;
uint pad0;
uint pad1;
};
struct GroupLayout {
uint base_lo;
uint base_hi;
uint row_stride;
uint pad;
};
struct TreeNode {
uint group;
uint column;
int left;
int right;
uint left_bins[8];
};
struct TreeParams {
uint n;
uint num_nodes;
uint pad0;
uint pad1;
};
struct RankParams {
uint query_begin;
uint num_queries;
uint has_weight;
uint norm;
uint truncation_level;
float sigmoid;
float sigmoid_min_hi;
float sigmoid_min_lo;
float sigmoid_factor_hi;
float sigmoid_factor_lo;
uint sigmoid_last;
uint pad;
};
DEVICE_FN uint min_u32(uint a, uint b) {
return a < b ? a : b;
}
DEVICE_FN float clamp_f32(float v, float lo, float hi) {
return v < lo ? lo : (v > hi ? hi : v);
}
DEVICE_FN float max_f32(float a, float b) {
return (b > a || a != a) ? b : a;
}
DEVICE_FN u64 join_u64(uint lo, uint hi) {
return ((u64)hi << 32) | (u64)lo;
}
DEVICE_FN int clamp_to_int(float value, int lo, int hi) {
if (value != value) {
return 0 < lo ? lo : (0 > hi ? hi : 0);
}
if (value <= (float)lo) {
return lo;
}
if (value >= (float)hi) {
return hi;
}
return (int)value;
}
DEVICE_FN uint bit_set(uint word, uint bin) {
return (word >> (bin & 31u)) & 1u;
}
DEVICE_FN HistParams hist_rows(HistParams p, CGPTR(uint) left_total) {
if (p.side == HIST_SIDE_LEFT) {
p.count = left_total[0];
} else if (p.side == HIST_SIDE_RIGHT) {
p.begin += left_total[0];
p.count -= left_total[0];
}
return p;
}
DEVICE_FN uint mix32(uint x) {
x ^= x >> 16;
x *= 0x7feb352du;
x ^= x >> 15;
x *= 0x846ca68bu;
x ^= x >> 16;
return x;
}
DEVICE_FN uint hash_draw(uint seed, uint stream, uint iteration, uint row_lo, uint row_hi) {
uint row_hash = mix32(row_lo ^ mix32(row_hi));
return mix32(seed ^ mix32(stream ^ mix32(iteration ^ row_hash)));
}
DEVICE_FN float uniform01(uint seed, uint stream, uint iteration, uint row_lo, uint row_hi) {
return (float)(hash_draw(seed, stream, iteration, row_lo, row_hi) >> 8) * (1.0f / 16777216.0f);
}
DEVICE_FN int quantize_grad(QuantParams p, float grad, uint row_lo, uint row_hi) {
float q;
if (p.stochastic != 0u) {
float u = uniform01(p.seed, 0u, p.iteration, row_lo, row_hi);
q = grad >= 0.0f ? F32_TRUNC(F32_FMA(grad, p.inv_grad_scale, u))
: F32_TRUNC(F32_FMA(grad, p.inv_grad_scale, -u));
} else {
q = F32_RINT(grad * p.inv_grad_scale);
}
return clamp_to_int(q, -p.grad_max_q, p.grad_max_q);
}
DEVICE_FN int quantize_hess(QuantParams p, float hess, uint row_lo, uint row_hi) {
if (p.constant_hessian != 0u) {
return 1;
}
float q;
if (p.stochastic != 0u) {
float u = uniform01(p.seed, 1u, p.iteration, row_lo, row_hi);
q = F32_TRUNC(F32_FMA(hess, p.inv_hess_scale, u));
} else {
q = F32_RINT(hess * p.inv_hess_scale);
}
return clamp_to_int(q, 0, p.hess_max_q);
}
DEVICE_FN i64 to_fixed(float value, float scale) {
float q = F32_RINT(value * scale);
return q != q ? (i64)0 : (i64)q;
}
DEVICE_FN uint scan_exclusive(SPTR(uint) buf, uint lid, uint size, uint value, SPTR(uint) total) {
buf[lid] = value;
BARRIER();
for (uint offset = 1u; offset < size; offset <<= 1) {
uint add = lid >= offset ? buf[lid - offset] : 0u;
BARRIER();
buf[lid] += add;
BARRIER();
}
uint inclusive = buf[lid];
if (lid == size - 1u) {
total[0] = inclusive;
}
BARRIER();
return inclusive - value;
}