update sched benchmark, created unit test to cover rbg search algorithms, improved algorithms to search for empty rbgs

This commit is contained in:
Francisco 2021-05-18 15:13:57 +01:00 committed by Francisco Paisana
parent 8ffbf0ff6d
commit f0f99c1e4f
4 changed files with 94 additions and 23 deletions

View File

@ -19,20 +19,10 @@ namespace srsenb {
rbg_interval rbg_interval::find_first_interval(const rbgmask_t& mask)
{
int rb_start = -1;
for (uint32_t i = 0; i < mask.size(); i++) {
if (rb_start == -1) {
if (mask.test(i)) {
rb_start = i;
}
} else {
if (!mask.test(i)) {
return rbg_interval(rb_start, i);
}
}
}
int rb_start = mask.find_lowest(0, mask.size());
if (rb_start != -1) {
return rbg_interval(rb_start, mask.size());
int rb_end = mask.find_lowest(rb_start + 1, mask.size(), false);
return rbg_interval(rb_start, rb_end < 0 ? mask.size() : rb_end);
}
return rbg_interval();
}
@ -61,7 +51,7 @@ RBInterval find_contiguous_interval(const RBMask& in_mask, uint32_t max_size)
}
size_t max_pos = std::min(in_mask.size(), (size_t)pos + max_size);
int pos2 = in_mask.find_lowest(pos, max_pos, true);
int pos2 = in_mask.find_lowest(pos + 1, max_pos, true);
RBInterval interv(pos, pos2 < 0 ? max_pos : pos2);
if (interv.length() >= max_size) {
return interv;

View File

@ -70,3 +70,7 @@ add_test(sched_benchmark_test sched_benchmark_test)
add_executable(sched_cqi_test sched_cqi_test.cc)
target_link_libraries(sched_cqi_test srsran_common srsenb_mac srsran_mac sched_test_common)
add_test(sched_cqi_test sched_cqi_test)
add_executable(sched_phy_resource_test sched_phy_resource_test.cc)
target_link_libraries(sched_phy_resource_test srsran_common srsenb_mac srsran_mac sched_test_common)
add_test(sched_phy_resource_test sched_phy_resource_test)

View File

@ -28,7 +28,7 @@ struct run_params {
struct run_params_range {
std::vector<uint32_t> nof_prbs{srsran::lte_cell_nof_prbs.begin(), srsran::lte_cell_nof_prbs.end()};
std::vector<uint32_t> nof_ues = {1, 2, 5};
std::vector<uint32_t> nof_ues = {1, 2, 5, 32};
uint32_t nof_ttis = 10000;
std::vector<uint32_t> cqi = {5, 10, 15};
std::vector<const char*> sched_policy = {"time_rr", "time_pf"};
@ -80,8 +80,9 @@ public:
std::vector<sched_interface::ul_sched_res_t> ul_result;
struct throughput_stats {
srsran::rolling_average<float> mean_dl_tbs, mean_ul_tbs, avg_dl_mcs, avg_ul_mcs;
srsran::rolling_average<float> avg_latency;
srsran::rolling_average<float> mean_dl_tbs, mean_ul_tbs, avg_dl_mcs, avg_ul_mcs;
srsran::rolling_average<double> avg_latency;
std::vector<uint32_t> latency_samples;
};
throughput_stats total_stats;
@ -98,6 +99,7 @@ public:
std::chrono::time_point<std::chrono::steady_clock> tp2 = std::chrono::steady_clock::now();
std::chrono::nanoseconds tdur = std::chrono::duration_cast<std::chrono::nanoseconds>(tp2 - tp);
total_stats.avg_latency.push(tdur.count());
total_stats.latency_samples.push_back(tdur.count());
}
sf_output_res_t sf_out{get_cell_params(), tti_rx, ul_result, dl_result};
@ -155,6 +157,7 @@ struct run_data {
float avg_dl_mcs;
float avg_ul_mcs;
std::chrono::microseconds avg_latency;
std::chrono::microseconds q0_9_latency;
};
int run_benchmark_scenario(run_params params, std::vector<run_data>& run_results)
@ -193,12 +196,14 @@ int run_benchmark_scenario(run_params params, std::vector<run_data>& run_results
tester.advance_tti();
ue_db_ctxt = tester.get_enb_ctxt().ue_db;
}
tester.total_stats = {};
// Run benchmark
tester.total_stats = {};
tester.total_stats.latency_samples.reserve(params.nof_ttis);
for (uint32_t count = 0; count < params.nof_ttis; ++count) {
tester.advance_tti();
}
std::sort(tester.total_stats.latency_samples.begin(), tester.total_stats.latency_samples.end());
run_data run_result = {};
run_result.params = params;
@ -206,7 +211,9 @@ int run_benchmark_scenario(run_params params, std::vector<run_data>& run_results
run_result.avg_ul_throughput = tester.total_stats.mean_ul_tbs.value() * 8.0F / 1e-3F;
run_result.avg_dl_mcs = tester.total_stats.avg_dl_mcs.value();
run_result.avg_ul_mcs = tester.total_stats.avg_ul_mcs.value();
run_result.avg_latency = std::chrono::microseconds(static_cast<int>(tester.total_stats.avg_latency.value() / 1000));
run_result.avg_latency = std::chrono::microseconds(static_cast<int>(tester.total_stats.avg_latency.value() / 1000));
run_result.q0_9_latency = std::chrono::microseconds(
tester.total_stats.latency_samples[static_cast<size_t>(tester.total_stats.latency_samples.size() * 0.9)] / 1000);
run_results.push_back(run_result);
return SRSRAN_SUCCESS;
@ -248,9 +255,9 @@ run_data expected_run_result(run_params params)
void print_benchmark_results(const std::vector<run_data>& run_results)
{
srslog::flush();
fmt::print("run | Nprb | cqi | sched pol | Nue | DL/UL [Mbps] | DL/UL mcs | DL/UL OH [%] | latency "
fmt::print("run | Nprb | cqi | sched pol | Nue | DL/UL [Mbps] | DL/UL mcs | DL/UL OH [%] | latency | latency q0.9 "
"[usec]\n");
fmt::print("---------------------------------------------------------------------------------------"
fmt::print("------------------------------------------------------------------------------------------------------"
"------\n");
for (uint32_t i = 0; i < run_results.size(); ++i) {
const run_data& r = run_results[i];
@ -263,7 +270,7 @@ void print_benchmark_results(const std::vector<run_data>& run_results)
tbs = srsran_ra_tbs_from_idx(tbs_idx, nof_pusch_prbs);
float ul_rate_overhead = 1.0F - r.avg_ul_throughput / (static_cast<float>(tbs) * 1e3F);
fmt::print("{:>3d}{:>6d}{:>6d}{:>12}{:>6d}{:>9.2}/{:>4.2}{:>9.1f}/{:>4.1f}{:9.1f}/{:>4.1f}{:12d}\n",
fmt::print("{:>3d}{:>6d}{:>6d}{:>12}{:>6d}{:>9.2}/{:>4.2}{:>9.1f}/{:>4.1f}{:9.1f}/{:>4.1f}{:>9d}{:12d}\n",
i,
r.params.nof_prbs,
r.params.cqi,
@ -275,7 +282,8 @@ void print_benchmark_results(const std::vector<run_data>& run_results)
r.avg_ul_mcs,
dl_rate_overhead * 100,
ul_rate_overhead * 100,
r.avg_latency.count());
r.avg_latency.count(),
r.q0_9_latency.count());
}
}

View File

@ -0,0 +1,69 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsenb/hdr/stack/mac/sched_phy_ch/sched_phy_resource.h"
#include "srsran/common/common_lte.h"
#include "srsran/common/test_common.h"
#include <random>
namespace srsenb {
std::random_device rd;
std::mt19937 rand_gen(rd());
uint32_t get_rand_Nrbg()
{
return cell_nof_prb_to_rbg(srsran::lte_cell_nof_prbs[std::uniform_int_distribution<uint32_t>{
0, srsran::lte_cell_nof_prbs.size() - 1}(rand_gen)]);
}
void test_rbg_mask_helpers()
{
rbgmask_t rbgs(MAX_NOF_RBGS);
// TEST: Find contiguous range of zero RBGs in RBG mask
rbgs.set(0);
rbgs.set(2);
rbg_interval interv = find_empty_rbg_interval(1, rbgs);
TESTASSERT(not interv.empty() and interv.length() == 1 and interv.start() == 1);
interv = find_empty_rbg_interval(2, rbgs);
TESTASSERT(not interv.empty() and interv.length() == 2 and interv.start() == 3);
interv = find_empty_rbg_interval(rbgs.size(), rbgs);
TESTASSERT(interv.length() + 3 == rbgs.size() and interv.start() == 3);
// TEST: find mask of zero RBGs in RBG mask
rbgmask_t empty_rbgs = find_available_rbgmask(1, false, rbgs);
TESTASSERT(empty_rbgs.count() == 1 and empty_rbgs.test(1));
empty_rbgs = find_available_rbgmask(5, false, rbgs);
TESTASSERT(empty_rbgs.count() == 5 and empty_rbgs.test(1) and empty_rbgs.test(3) and not empty_rbgs.test(2));
// TEST: find mask of zero RBGs in random RBG mask
std::bernoulli_distribution dist{0.5};
rbgs = rbgmask_t(get_rand_Nrbg());
for (size_t i = 0; i < rbgs.size(); ++i) {
rbgs.set(i, dist(rand_gen));
}
empty_rbgs = find_available_rbgmask(rbgs.size(), false, rbgs);
TESTASSERT(empty_rbgs == ~rbgs);
uint32_t L = std::uniform_int_distribution<uint32_t>{1, (uint32_t)rbgs.size() - 1}(rand_gen);
empty_rbgs = find_available_rbgmask(L, false, rbgs);
TESTASSERT(empty_rbgs.count() <= L and (empty_rbgs & rbgs).none());
uint32_t nprb = count_prb_per_tb(rbgs);
TESTASSERT(nprb <= MAX_NOF_PRBS);
}
} // namespace srsenb
int main()
{
srsenb::test_rbg_mask_helpers();
}