Optimization of sched_ue methods to derive required number of prbs to allocate to a rnti

This optimization has been achieved by:
- implementation of "false position method" root-finding algorithm
- application of the false position method in cc_sched_ue::get_required_prb_dl/ul(...)

The number of iterations in the worst case scenario, reduced from 100 to 5 with
the proposed algorithm.
master
Francisco 4 years ago committed by Andre Puschmann
parent 2dc3fce9bd
commit 94efeab672

@ -89,6 +89,65 @@ bool operator==(const sched_interface::ue_cfg_t::cc_cfg_t& lhs, const sched_inte
return lhs.enb_cc_idx == rhs.enb_cc_idx and lhs.active == rhs.active;
}
template <typename YType, typename Callable, typename ErrorDetect>
std::tuple<int, YType, int, YType> false_position_method(int x1, int x2, YType y0, const Callable& f)
{
return false_position_method(x1, x2, y0, f, []() { return false; });
}
template <typename YType, typename Callable, typename ErrorDetect>
std::tuple<int, YType, int, YType>
false_position_method(int x1, int x2, YType y0, const Callable& f, const ErrorDetect& is_error)
{
static_assert(std::is_same<YType, decltype(f(x1))>::value,
"The type of the final result and callable return do not match\n");
YType y1 = f(x1);
if (is_error(y1) or y1 >= y0) {
return {x1, y1, x1, y1};
}
YType y2 = f(x2);
if (is_error(y2) or y2 <= y0) {
return {x2, y2, x2, y2};
}
YType y3;
while (x2 > x1 + 1) {
int x3 = round(x1 - ((x2 - x1) * (y1 - y0) / (float)(y2 - y1)));
if (x3 == x2) {
y3 = y2;
// check if in frontier
YType y3_1 = f(x3 - 1);
if (not is_error(y3_1) and y3_1 < y0) {
return {x3 - 1, y3_1, x3, y3};
} else {
x3--;
y3 = y3_1;
}
} else if (x3 == x1) {
y3 = y1;
// check if in frontier
YType y3_1 = f(x3 + 1);
if (not is_error(y3_1) and y3_1 >= y0) {
return {x3, y3, x3 + 1, y3_1};
} else {
x3++;
y3 = y3_1;
}
} else {
y3 = f(x3);
if (is_error(y3) or y3 == y0) {
return {x3, y3, x3, y3};
}
}
if (y3 < y0) {
x1 = x3;
y1 = y3;
} else {
x2 = x3;
y2 = y3;
}
}
return {x1, y1, x2, y2};
}
/*******************************************************
*
* Initialization and configuration functions
@ -1425,68 +1484,46 @@ int cc_sched_ue::alloc_tbs_ul(uint32_t nof_prb, uint32_t nof_re, uint32_t req_by
int cc_sched_ue::get_required_prb_dl(uint32_t req_bytes, uint32_t nof_ctrl_symbols)
{
int mcs = 0;
uint32_t nof_re = 0;
int tbs = 0;
uint32_t nbytes = 0;
uint32_t n;
for (n = 0; n < cell_params->nof_prb() and nbytes < req_bytes; ++n) {
nof_re = srslte_ra_dl_approx_nof_re(&cell_params->cfg.cell, n + 1, nof_ctrl_symbols);
auto compute_tbs_approx = [this, nof_ctrl_symbols](uint32_t nof_prb) {
uint32_t nof_re = srslte_ra_dl_approx_nof_re(&cell_params->cfg.cell, nof_prb, nof_ctrl_symbols);
int mcs, tbs;
if (fixed_mcs_dl < 0 or not dl_cqi_rx) {
tbs = alloc_tbs_dl(n + 1, nof_re, 0, &mcs);
} else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl, cfg->use_tbs_index_alt, false), n + 1) / 8;
return alloc_tbs_dl(nof_prb, nof_re, 0, &mcs);
}
if (tbs > 0) {
nbytes = tbs;
} else if (tbs < 0) {
return 0;
}
}
return srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl, cfg->use_tbs_index_alt, false), nof_prb) / 8;
};
return (nbytes >= req_bytes) ? n : -1;
std::tuple<uint32_t, int, uint32_t, int> ret = false_position_method(
1u, cell_params->nof_prb(), (int)req_bytes, compute_tbs_approx, [](int y) { return y == SRSLTE_ERROR; });
int upper_tbs = std::get<3>(ret);
uint32_t upper_nprb = std::get<2>(ret);
return (upper_tbs < 0) ? 0 : ((upper_tbs < (int)req_bytes) ? -1 : upper_nprb);
}
uint32_t cc_sched_ue::get_required_prb_ul(uint32_t req_bytes)
{
int mcs = 0;
uint32_t nbytes = 0;
uint32_t N_srs = 0;
uint32_t n = 0;
if (req_bytes == 0) {
return 0;
}
uint32_t last_valid_n = 0;
for (n = 1; n < cell_params->nof_prb() && nbytes < req_bytes + 4; n++) {
uint32_t nof_re = (2 * (SRSLTE_CP_NSYMB(cell_params->cfg.cell.cp) - 1) - N_srs) * n * SRSLTE_NRE;
int tbs = 0;
auto compute_tbs_approx = [this](uint32_t nof_prb) {
const uint32_t N_srs = 0;
uint32_t nof_re = (2 * (SRSLTE_CP_NSYMB(cell_params->cfg.cell.cp) - 1) - N_srs) * nof_prb * SRSLTE_NRE;
int mcs, tbs;
if (fixed_mcs_ul < 0) {
tbs = alloc_tbs_ul(n, nof_re, 0, &mcs);
} else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_ul, false, true), n) / 8;
}
if (tbs > 0) {
nbytes = tbs;
last_valid_n = n;
return alloc_tbs_ul(nof_prb, nof_re, 0, &mcs);
}
}
if (last_valid_n > 0) {
if (n != last_valid_n) {
n = last_valid_n;
}
while (!srslte_dft_precoding_valid_prb(n) && n <= cell_params->nof_prb()) {
n++;
}
return n;
} else {
// This should never happen. Just in case, return 0 PRB and handle it later
log_h->error("SCHED: Could not obtain any valid number of PRB for an uplink allocation\n");
return 0;
}
return srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_ul, false, true), nof_prb) / 8;
};
// find nof prbs that lead to a tbs just above req_bytes
int target_tbs = req_bytes + 4;
std::tuple<uint32_t, int, uint32_t, int> ret = false_position_method(
1u, cell_params->nof_prb(), target_tbs, compute_tbs_approx, [](int y) { return y == SRSLTE_ERROR; });
uint32_t req_prbs = std::get<2>(ret);
while (!srslte_dft_precoding_valid_prb(req_prbs) && req_prbs < cell_params->nof_prb()) {
req_prbs++;
}
return req_prbs;
}
void cc_sched_ue::set_dl_cqi(uint32_t tti_tx_dl, uint32_t dl_cqi_)

Loading…
Cancel
Save