Skip to content

Commit 8248726

Browse files
committed
sched: extend unit tests for slice scheduler and rewrote the prioritization mechanism
1 parent c6b218e commit 8248726

File tree

6 files changed

+293
-148
lines changed

6 files changed

+293
-148
lines changed

lib/scheduler/slicing/ran_slice_candidate.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ template <bool IsDl>
2020
class common_ran_slice_candidate
2121
{
2222
public:
23-
common_ran_slice_candidate(ran_slice_instance& instance_) : inst(&instance_) {}
23+
common_ran_slice_candidate(ran_slice_instance& instance_, unsigned max_rbs_ = 0) :
24+
inst(&instance_), max_rbs(max_rbs_ == 0 ? inst->cfg.max_prb : max_rbs_)
25+
{
26+
}
2427

2528
ran_slice_id_t id() const { return inst->id; }
2629
[[nodiscard]] const slice_rrm_policy_config& cfg() const { return inst->cfg; }
@@ -43,13 +46,14 @@ class common_ran_slice_candidate
4346
[[nodiscard]] unsigned remaining_rbs() const
4447
{
4548
if constexpr (IsDl) {
46-
return inst->cfg.max_prb < inst->pdsch_rb_count ? 0 : inst->cfg.max_prb - inst->pdsch_rb_count;
49+
return max_rbs < inst->pdsch_rb_count ? 0 : max_rbs - inst->pdsch_rb_count;
4750
}
48-
return inst->cfg.max_prb < inst->pusch_rb_count ? 0 : inst->cfg.max_prb - inst->pusch_rb_count;
51+
return max_rbs < inst->pusch_rb_count ? 0 : max_rbs - inst->pusch_rb_count;
4952
}
5053

5154
protected:
52-
ran_slice_instance* inst = nullptr;
55+
ran_slice_instance* inst = nullptr;
56+
unsigned max_rbs = 0;
5357
};
5458

5559
} // namespace detail

lib/scheduler/slicing/ran_slice_instance.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ void ran_slice_instance::slot_indication()
2323
{
2424
pdsch_rb_count = 0;
2525
pusch_rb_count = 0;
26-
pdsch_complete = false;
27-
pusch_complete = false;
2826
}
2927

3028
void ran_slice_instance::add_logical_channel(du_ue_index_t ue_idx, lcid_t lcid)

lib/scheduler/slicing/ran_slice_instance.h

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,43 +21,18 @@ namespace srsran {
2121
class ran_slice_instance
2222
{
2323
public:
24-
constexpr static int skip_slice_prio = std::numeric_limits<int>::min();
25-
constexpr static int default_slice_prio = 0;
26-
2724
ran_slice_instance(ran_slice_id_t id_, const cell_configuration& cell_cfg_, const slice_rrm_policy_config& cfg_);
2825

2926
void slot_indication();
3027

3128
bool active() const { return not bearers.empty(); }
3229

33-
int get_dl_prio()
34-
{
35-
if (not active() or pdsch_complete or cfg.max_prb <= pdsch_rb_count) {
36-
return skip_slice_prio;
37-
}
38-
return cfg.min_prb > pdsch_rb_count ? cfg.min_prb - pdsch_rb_count : default_slice_prio;
39-
}
40-
41-
int get_ul_prio()
42-
{
43-
if (not active() or pusch_complete or cfg.max_prb <= pusch_rb_count) {
44-
return skip_slice_prio;
45-
}
46-
return cfg.min_prb > pusch_rb_count ? cfg.min_prb - pusch_rb_count : default_slice_prio;
47-
}
48-
4930
/// Save PDSCH grant.
5031
void store_pdsch_grant(unsigned crbs) { pdsch_rb_count += crbs; }
5132

5233
/// Save PUSCH grant.
5334
void store_pusch_grant(unsigned crbs) { pusch_rb_count += crbs; }
5435

55-
/// Mark the allocation of PDSCH for this slice and the current slot as complete.
56-
void set_pdsch_scheduled() { pdsch_complete = true; }
57-
58-
/// Mark the allocation of PUSCH for this slice and the current slot as complete.
59-
void set_pusch_scheduled() { pusch_complete = true; }
60-
6136
/// Determine if at least one bearer of the given UE is currently managed by this slice.
6237
bool contains(du_ue_index_t ue_idx) const { return bearers.contains(ue_idx); }
6338

@@ -85,10 +60,6 @@ class ran_slice_instance
8560
unsigned pdsch_rb_count = 0;
8661
/// Counter of how many RBs have been scheduled for PUSCH in the current slot for this slice.
8762
unsigned pusch_rb_count = 0;
88-
89-
private:
90-
bool pdsch_complete = false;
91-
bool pusch_complete = false;
9263
};
9364

9465
} // namespace srsran

lib/scheduler/slicing/slice_scheduler.cpp

Lines changed: 89 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -19,46 +19,40 @@ slice_scheduler::slice_scheduler(const cell_configuration& cell_cfg_) :
1919
{
2020
// Create a number of slices equal to the number of configured RRM Policy members + 1 (default slice).
2121
slices.reserve(cell_cfg.rrm_policy_members.size() + 1);
22-
sorted_dl_prios.reserve(cell_cfg.rrm_policy_members.size() + 1);
23-
sorted_ul_prios.reserve(cell_cfg.rrm_policy_members.size() + 1);
2422

2523
// Create RAN slice instances.
2624
ran_slice_id_t id_count{0};
2725
// Default slice.
2826
slices.emplace_back(id_count, cell_cfg, slice_rrm_policy_config{});
29-
slices.back().policy =
27+
slices.back().inst.policy =
3028
create_scheduler_strategy(scheduler_strategy_params{"time_rr", &logger}, cell_cfg.expert_cfg.ue);
31-
sorted_dl_prios.emplace_back(id_count);
32-
sorted_ul_prios.emplace_back(id_count);
3329
++id_count;
3430
// Configured RRM policy members
3531
for (const slice_rrm_policy_config& rrm : cell_cfg.rrm_policy_members) {
3632
slices.emplace_back(id_count, cell_cfg, rrm);
37-
slices.back().policy =
33+
slices.back().inst.policy =
3834
create_scheduler_strategy(scheduler_strategy_params{"time_rr", &logger}, cell_cfg.expert_cfg.ue);
39-
sorted_dl_prios.emplace_back(id_count);
40-
sorted_ul_prios.emplace_back(id_count);
4135
++id_count;
4236
}
4337
}
4438

4539
void slice_scheduler::slot_indication()
4640
{
41+
slot_count++;
42+
43+
// Update the context of each slice.
4744
for (auto& slice : slices) {
48-
slice.slot_indication();
45+
slice.inst.slot_indication();
4946
}
5047

51-
// Compute slice priorities.
52-
for (slice_prio_context& ctx : sorted_dl_prios) {
53-
ctx.prio = slices[ctx.id.value()].get_dl_prio();
54-
}
55-
for (slice_prio_context& ctx : sorted_ul_prios) {
56-
ctx.prio = slices[ctx.id.value()].get_ul_prio();
48+
// Recompute the priority queues.
49+
dl_prio_queue.clear();
50+
ul_prio_queue.clear();
51+
for (const auto& slice : slices) {
52+
unsigned max_rbs = slice.inst.cfg.min_prb > 0 ? slice.inst.cfg.min_prb : slice.inst.cfg.max_prb;
53+
dl_prio_queue.push(slice_candidate_context{slice.inst.id, slice.get_prio(true, slot_count, false), {0, max_rbs}});
54+
ul_prio_queue.push(slice_candidate_context{slice.inst.id, slice.get_prio(false, slot_count, false), {0, max_rbs}});
5755
}
58-
59-
// Sort slices by descending priority.
60-
std::sort(sorted_dl_prios.begin(), sorted_dl_prios.end(), std::greater<>{});
61-
std::sort(sorted_ul_prios.begin(), sorted_ul_prios.end(), std::greater<>{});
6256
}
6357

6458
void slice_scheduler::add_ue(const ue_configuration& ue_cfg)
@@ -87,83 +81,104 @@ void slice_scheduler::reconf_ue(const ue_configuration& next_ue_cfg, const ue_co
8781
void slice_scheduler::rem_ue(du_ue_index_t ue_idx)
8882
{
8983
for (auto& slice : slices) {
90-
slice.rem_ue(ue_idx);
84+
slice.inst.rem_ue(ue_idx);
9185
}
9286
}
9387

9488
ran_slice_instance& slice_scheduler::get_slice(const rrm_policy_member& rrm)
9589
{
96-
auto it = std::find_if(
97-
slices.begin(), slices.end(), [&rrm](const ran_slice_instance& slice) { return slice.cfg.rrc_member == rrm; });
90+
auto it = std::find_if(slices.begin() + 1, slices.end(), [&rrm](const ran_slice_sched_context& slice) {
91+
return slice.inst.cfg.rrc_member == rrm;
92+
});
9893
if (it == slices.end()) {
9994
// Slice with the provided RRM policy member was not found. Return default slice.
100-
return slices.front();
95+
return slices.front().inst;
10196
}
102-
return *it;
97+
return it->inst;
10398
}
10499

105-
std::optional<dl_ran_slice_candidate> slice_scheduler::get_next_dl_candidate()
100+
template <bool IsDownlink>
101+
std::optional<std::conditional_t<IsDownlink, dl_ran_slice_candidate, ul_ran_slice_candidate>>
102+
slice_scheduler::get_next_candidate()
106103
{
107-
if (slices.size() == 1) {
108-
return create_dl_candidate();
109-
}
110-
111-
// Check if the slice priority hasn't changed. If it did, recompute priorities.
112-
slice_prio_context* slice_prio_ctxt = &sorted_dl_prios.front();
113-
// Recompute priority
114-
int prio = slices[slice_prio_ctxt->id.value()].get_dl_prio();
115-
if (prio != slice_prio_ctxt->prio) {
116-
// Priority changed
117-
slice_prio_ctxt->prio = prio;
118-
// Check if sort needs to be called again
119-
// Note: This assumes that only the previous front slice was used in scheduling.
120-
if (prio < sorted_dl_prios[1].prio) {
121-
// Slices need to be reordered.
122-
std::sort(sorted_dl_prios.begin(), sorted_dl_prios.end(), std::greater<>{});
104+
slice_prio_queue& prio_queue = IsDownlink ? dl_prio_queue : ul_prio_queue;
105+
while (not prio_queue.empty()) {
106+
ran_slice_sched_context& chosen_slice = slices[prio_queue.top().id.value()];
107+
interval<unsigned> rb_lims = prio_queue.top().rb_lims;
108+
prio_queue.pop();
109+
110+
unsigned rb_count = IsDownlink ? chosen_slice.inst.pdsch_rb_count : chosen_slice.inst.pusch_rb_count;
111+
if (not rb_lims.contains(rb_count)) {
112+
// The slice has been scheduled in this slot with a number of RBs that is not within the limits for this
113+
// candidate. This could happen, for instance, if the scheduler could not schedule all RBs of a candidate
114+
// bounded between {0, minRB}. In this case, the second candidate for the same slice with bounds {minRB, maxRB}
115+
// is skipped.
116+
continue;
123117
}
124-
}
125118

126-
return create_dl_candidate();
127-
}
119+
const slice_rrm_policy_config& cfg = chosen_slice.inst.cfg;
120+
if (cfg.min_prb != cfg.max_prb and rb_lims.stop() == cfg.min_prb) {
121+
// For the special case when minRB ratio>0, the first candidate for this slice was bounded between {0, minRB}.
122+
// We re-add the slice as a candidate, this time, with RB bounds {minRB, maxRB}.
123+
priority_type prio = chosen_slice.get_prio(true, slot_count, true);
124+
prio_queue.push(slice_candidate_context{chosen_slice.inst.id, prio, {cfg.min_prb, cfg.max_prb}});
125+
}
128126

129-
std::optional<ul_ran_slice_candidate> slice_scheduler::get_next_ul_candidate()
130-
{
131-
if (slices.size() == 1) {
132-
return create_ul_candidate();
133-
}
127+
// Save current slot count.
128+
unsigned& count_to_set = IsDownlink ? chosen_slice.last_dl_slot : chosen_slice.last_ul_slot;
129+
count_to_set = slot_count;
134130

135-
// Check if the slice priority hasn't changed. If it did, recompute priorities.
136-
slice_prio_context* slice_prio_ctxt = &sorted_ul_prios.front();
137-
// Recompute priority
138-
int prio = slices[slice_prio_ctxt->id.value()].get_ul_prio();
139-
if (prio != slice_prio_ctxt->prio) {
140-
// Priority changed
141-
slice_prio_ctxt->prio = prio;
142-
// Check if sort needs to be called again
143-
// Note: This assumes that only the previous front slice was used in scheduling.
144-
if (prio < sorted_ul_prios[1].prio) {
145-
// Slices need to be reordered.
146-
std::sort(sorted_ul_prios.begin(), sorted_ul_prios.end(), std::greater<>{});
147-
}
131+
// Return the candidate.
132+
return std::conditional_t<IsDownlink, dl_ran_slice_candidate, ul_ran_slice_candidate>{chosen_slice.inst,
133+
rb_lims.stop()};
148134
}
135+
return std::nullopt;
136+
}
149137

150-
return create_ul_candidate();
138+
std::optional<dl_ran_slice_candidate> slice_scheduler::get_next_dl_candidate()
139+
{
140+
return get_next_candidate<true>();
151141
}
152142

153-
std::optional<dl_ran_slice_candidate> slice_scheduler::create_dl_candidate()
143+
std::optional<ul_ran_slice_candidate> slice_scheduler::get_next_ul_candidate()
154144
{
155-
if (sorted_dl_prios[0].prio != ran_slice_instance::skip_slice_prio) {
156-
slices[sorted_dl_prios[0].id.value()].set_pdsch_scheduled();
157-
return dl_ran_slice_candidate{slices[sorted_dl_prios[0].id.value()]};
158-
}
159-
return std::nullopt;
145+
return get_next_candidate<false>();
160146
}
161147

162-
std::optional<ul_ran_slice_candidate> slice_scheduler::create_ul_candidate()
148+
slice_scheduler::priority_type slice_scheduler::ran_slice_sched_context::get_prio(bool is_dl,
149+
slot_count_type current_slot_count,
150+
bool slice_resched) const
163151
{
164-
if (sorted_ul_prios[0].prio != ran_slice_instance::skip_slice_prio) {
165-
slices[sorted_ul_prios[0].id.value()].set_pusch_scheduled();
166-
return ul_ran_slice_candidate{slices[sorted_ul_prios[0].id.value()]};
152+
// Note: The positive integer representing the priority of a slice consists of a concatenation of three priority
153+
// values:
154+
// 1. slice traffic priority (16 bits). Differentiation of slices based on whether they have minimum required
155+
// traffic agreements (e.g. minRB ratio).
156+
// 2. delay priority (8 bits), which attributes the highest priority to slices that have not been scheduled for a
157+
// long time
158+
// 3. round-robin based on slot indication count (8 bits).
159+
160+
// Priority when slice has already reached its minimum RB ratio agreement.
161+
constexpr static priority_type default_prio = 0x1U;
162+
// Priority when slice still needs to reach its minimum RB ratio agreement.
163+
constexpr static priority_type high_prio = 0x2U;
164+
constexpr static priority_type delay_bitsize = 8U;
165+
constexpr static priority_type rr_bitsize = 8U;
166+
167+
unsigned rb_count = is_dl ? inst.pdsch_rb_count : inst.pusch_rb_count;
168+
if (not inst.active() or rb_count >= inst.cfg.max_prb) {
169+
// If the slice is not in a state to be scheduled in this slot, return skip priority level.
170+
return skip_prio;
167171
}
168-
return std::nullopt;
172+
173+
// In case minRB > 0 and this is the first time the slice is proposed as a candidate, we give it a higher priority.
174+
priority_type slice_prio = inst.cfg.min_prb > 0 and not slice_resched ? high_prio : default_prio;
175+
176+
// Increase priorities of slices that have not been scheduled for a long time.
177+
unsigned last_count = is_dl ? last_dl_slot : last_ul_slot;
178+
priority_type delay_prio = (current_slot_count - last_count) & ((1U << delay_bitsize) - 1U);
179+
180+
// Round-robin across slices with the same slice and delay priorities.
181+
priority_type rr_prio = (inst.id.value() % current_slot_count) & ((1U << rr_bitsize) - 1U);
182+
183+
return (slice_prio << (delay_bitsize + rr_bitsize)) + (delay_prio << rr_bitsize) + rr_prio;
169184
}

0 commit comments

Comments
 (0)