From f0f99c1e4f43f1cffab16d3afbf352c9e73599b6 Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 18 May 2021 15:13:57 +0100 Subject: [PATCH] update sched benchmark, created unit test to cover rbg search algorithms, improved algorithms to search for empty rbgs --- .../mac/sched_phy_ch/sched_phy_resource.cc | 18 ++--- srsenb/test/mac/CMakeLists.txt | 4 ++ srsenb/test/mac/sched_benchmark.cc | 26 ++++--- srsenb/test/mac/sched_phy_resource_test.cc | 69 +++++++++++++++++++ 4 files changed, 94 insertions(+), 23 deletions(-) create mode 100644 srsenb/test/mac/sched_phy_resource_test.cc diff --git a/srsenb/src/stack/mac/sched_phy_ch/sched_phy_resource.cc b/srsenb/src/stack/mac/sched_phy_ch/sched_phy_resource.cc index 377288c14..f71e19879 100644 --- a/srsenb/src/stack/mac/sched_phy_ch/sched_phy_resource.cc +++ b/srsenb/src/stack/mac/sched_phy_ch/sched_phy_resource.cc @@ -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; diff --git a/srsenb/test/mac/CMakeLists.txt b/srsenb/test/mac/CMakeLists.txt index 40e5800b7..117372fe6 100644 --- a/srsenb/test/mac/CMakeLists.txt +++ b/srsenb/test/mac/CMakeLists.txt @@ -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) diff --git a/srsenb/test/mac/sched_benchmark.cc b/srsenb/test/mac/sched_benchmark.cc index 606013a1f..e86785576 100644 --- a/srsenb/test/mac/sched_benchmark.cc +++ b/srsenb/test/mac/sched_benchmark.cc @@ -28,7 +28,7 @@ struct run_params { struct run_params_range { std::vector nof_prbs{srsran::lte_cell_nof_prbs.begin(), srsran::lte_cell_nof_prbs.end()}; - std::vector nof_ues = {1, 2, 5}; + std::vector nof_ues = {1, 2, 5, 32}; uint32_t nof_ttis = 10000; std::vector cqi = {5, 10, 15}; std::vector sched_policy = {"time_rr", "time_pf"}; @@ -80,8 +80,9 @@ public: std::vector ul_result; struct throughput_stats { - srsran::rolling_average mean_dl_tbs, mean_ul_tbs, avg_dl_mcs, avg_ul_mcs; - srsran::rolling_average avg_latency; + srsran::rolling_average mean_dl_tbs, mean_ul_tbs, avg_dl_mcs, avg_ul_mcs; + srsran::rolling_average avg_latency; + std::vector latency_samples; }; throughput_stats total_stats; @@ -98,6 +99,7 @@ public: std::chrono::time_point tp2 = std::chrono::steady_clock::now(); std::chrono::nanoseconds tdur = std::chrono::duration_cast(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_results) @@ -193,12 +196,14 @@ int run_benchmark_scenario(run_params params, std::vector& 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_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(tester.total_stats.avg_latency.value() / 1000)); + run_result.avg_latency = std::chrono::microseconds(static_cast(tester.total_stats.avg_latency.value() / 1000)); + run_result.q0_9_latency = std::chrono::microseconds( + tester.total_stats.latency_samples[static_cast(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_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_results) tbs = srsran_ra_tbs_from_idx(tbs_idx, nof_pusch_prbs); float ul_rate_overhead = 1.0F - r.avg_ul_throughput / (static_cast(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_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()); } } diff --git a/srsenb/test/mac/sched_phy_resource_test.cc b/srsenb/test/mac/sched_phy_resource_test.cc new file mode 100644 index 000000000..0d9c85ff9 --- /dev/null +++ b/srsenb/test/mac/sched_phy_resource_test.cc @@ -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 + +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{ + 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{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(); +}