From 87402f4959cd34cad3775f5059eabfca1cd96a0f Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 5 Feb 2026 12:31:38 +0000 Subject: [PATCH] feat(nr_dlsch): option to provide the number of symbols per thread * Add option `--L1s.L1_num_tx_sym_per_thread` for the softmodems and `-Y` for `nr_dlsim` to provide the number of symbols processed per thread. It defaults to 0 which makes that every symbols are processed in one thread. * The last symbol processing task is processed in the L1 TX thread. --- executables/nr-gnb.c | 3 --- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 26 ++++++++++++++++++-------- openair1/SIMULATION/NR_PHY/dlsim.c | 9 ++++++++- openair2/GNB_APP/L1_nr_paramdef.h | 6 ++++++ openair2/GNB_APP/gnb_config.c | 3 +++ 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index dfb94d5ad9..abbfa05df1 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -307,9 +307,6 @@ void init_gNB_Tpool(int inst) PHY_VARS_gNB *gNB; gNB = RC.gNB[inst]; gNB_L1_proc_t *proc = &gNB->proc; - // PUSCH symbols per thread need to be calculated by how many threads we have - gNB->num_pusch_symbols_per_thread = 1; - gNB->num_pdsch_symbols_per_thread = 1; // ULSCH decoding threadpool initTpool(get_softmodem_params()->threadPoolConfig, &gNB->threadPool, cpumeas(CPUMEAS_GETSTATE)); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index e6ae850093..d227148353 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -669,9 +669,15 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC // spawn symbol threads - int nb_tasks = rel15->NrOfSymbols / gNB->num_pdsch_symbols_per_thread; - if ((rel15->NrOfSymbols % gNB->num_pdsch_symbols_per_thread) > 0) - nb_tasks++; + int nb_tasks = 1; + int num_pdsch_symbols_per_task = rel15->NrOfSymbols; + if (gNB->num_pdsch_symbols_per_thread > 0) { + // symbol processing in thread pool enabled + num_pdsch_symbols_per_task = gNB->num_pdsch_symbols_per_thread; + nb_tasks = rel15->NrOfSymbols / num_pdsch_symbols_per_task; + if ((rel15->NrOfSymbols % num_pdsch_symbols_per_task) > 0) + nb_tasks++; + } pdschSymbolProc_t arr[nb_tasks]; task_ans_t ans; init_task_ans(&ans, nb_tasks); @@ -679,7 +685,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC unsigned int re_beginning_of_symbol = 0; int res = 0; for (int l_symbol = rel15->StartSymbolIndex; l_symbol < rel15->StartSymbolIndex + rel15->NrOfSymbols; - l_symbol += gNB->num_pdsch_symbols_per_thread) { + l_symbol += num_pdsch_symbols_per_task) { pdschSymbolProc_t *rdata = &arr[sz_arr]; rdata->ans = &ans; ++sz_arr; @@ -690,8 +696,8 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC rdata->slot = slot; rdata->startSymbol = l_symbol; res = rel15->NrOfSymbols - (l_symbol - rel15->StartSymbolIndex); - if (res >= gNB->num_pdsch_symbols_per_thread) - rdata->numSymbols = gNB->num_pdsch_symbols_per_thread; + if (res >= num_pdsch_symbols_per_task) + rdata->numSymbols = num_pdsch_symbols_per_task; else rdata->numSymbols = res; rdata->layerSz2 = layerSz2; @@ -711,8 +717,12 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC reset_meas(&rdata->dlsch_precoding_stats); for (int l = 0; l < rel15->nrOfLayers; l++) rdata->tx_layers[l] = tx_layers[l]; - task_t t = {.func = &nr_pdsch_symbol_processing, .args = rdata}; - pushTpool(&gNB->threadPool, t); + if (l_symbol < rel15->StartSymbolIndex + rel15->NrOfSymbols - num_pdsch_symbols_per_task) { + task_t t = {.func = &nr_pdsch_symbol_processing, .args = rdata}; + pushTpool(&gNB->threadPool, t); + } else { + nr_pdsch_symbol_processing(rdata); + } } join_task_ans(&ans); for (int i = 0; i < nb_tasks; i++) { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index c6fc036bf8..2c08ab3b6e 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -382,6 +382,8 @@ int main(int argc, char **argv) uint8_t dlsch_threads = 0; int chest_type[2] = {0}; uint8_t max_ldpc_iterations = 5; + // number of PDSCH symbols per thread = 0 means do not use thread pool + int num_pdsch_symbols_per_thread = 0; if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) { exit_fun("[NR_DLSIM] Error, configuration module init failed\n"); } @@ -583,6 +585,10 @@ int main(int argc, char **argv) gNBthreads[sizeof(gNBthreads)-1]=0; break; + case 'Y': + num_pdsch_symbols_per_thread = atoi(optarg); + break; + case 'Z' : filename_csv = strdup(optarg); AssertFatal(filename_csv != NULL, "strdup() error: errno %d\n", errno); @@ -657,6 +663,7 @@ int main(int argc, char **argv) printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n"); printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:2} DMRS ConfType{1:2}, e.g. -U 3 0 2 1 \n"); printf("-X gNB thread pool configuration, n => no threads\n"); + printf("-Y Number of symbols processed per PDSCH generation thread\n"); printf("-Z Output filename (.csv format) for stats\n"); exit (-1); break; @@ -715,7 +722,7 @@ int main(int argc, char **argv) AssertFatal((gNB->if_inst = NR_IF_Module_init(0)) != NULL, "Cannot register interface"); gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; - gNB->num_pdsch_symbols_per_thread = 1; + gNB->num_pdsch_symbols_per_thread = num_pdsch_symbols_per_thread; NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(*scc));; prepare_scc(scc); diff --git a/openair2/GNB_APP/L1_nr_paramdef.h b/openair2/GNB_APP/L1_nr_paramdef.h index 1faa03c475..9e33c57795 100644 --- a/openair2/GNB_APP/L1_nr_paramdef.h +++ b/openair2/GNB_APP/L1_nr_paramdef.h @@ -28,6 +28,10 @@ #define L1_MAX_LDPC_ITERATIONS "max_ldpc_iterations" #define L1_RX_THREAD_CORE "L1_rx_thread_core" #define L1_TX_THREAD_CORE "L1_tx_thread_core" +#define L1_NUM_RX_SYM_PER_THREAD "L1_num_rx_sym_per_thread" +#define HLP_L1_NUM_RX_SYM_PER_THREAD "number of symbols processed per PUSCH generation thread" +#define L1_NUM_TX_SYM_PER_THREAD "L1_num_tx_sym_per_thread" +#define HLP_L1_NUM_TX_SYM_PER_THREAD "number of symbols processed per PDSCH generation thread" #define HLP_TP_SIZ "thread_pool_size paramter removed, please use --thread-pool" #define L1_TX_AMP_BACKOFF_dB "tx_amp_backoff_dB" #define HLP_L1TX_BO "Backoff from full-scale output at the L1 entity(frequency domain), ex. 12 would corresponding to 14-bit input level (6 dB/bit). Default 36 dBFS for OAI RU entity" @@ -58,6 +62,8 @@ {L1_MAX_LDPC_ITERATIONS, NULL, 0, .uptr=NULL, .defintval=8, TYPE_UINT, 0}, \ {L1_RX_THREAD_CORE, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ {L1_TX_THREAD_CORE, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ + {L1_NUM_RX_SYM_PER_THREAD, HLP_L1_NUM_RX_SYM_PER_THREAD, 0, .iptr=NULL, .defintval=1, TYPE_INT, 0}, \ + {L1_NUM_TX_SYM_PER_THREAD, HLP_L1_NUM_TX_SYM_PER_THREAD, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ {L1_TX_AMP_BACKOFF_dB, HLP_L1TX_BO,0, .uptr=NULL, .defintval=36, TYPE_UINT, 0}, \ {L1_PHASE_COMP, HLP_L1_PHASE_COMP,PARAMFLAG_BOOL, .uptr=NULL,.defintval=1, TYPE_UINT, 0}, \ {L1_NUM_ANTENNAS_PER_THREAD, HLP_NUM_ARX,0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 4928d98183..a73a77b0ee 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -841,6 +841,9 @@ void RCconfig_NR_L1(void) gNB->L1_rx_thread_core = *gpd(params, np, L1_RX_THREAD_CORE)->iptr; gNB->L1_tx_thread_core = *gpd(params, np, L1_TX_THREAD_CORE)->iptr; LOG_I(NR_PHY, "thread cores for L1_RX %d L1_TX %d\n", gNB->L1_rx_thread_core, gNB->L1_tx_thread_core); + // PUSCH symbols per thread need to be calculated by how many threads we have + gNB->num_pusch_symbols_per_thread = *gpd(params, np, L1_NUM_RX_SYM_PER_THREAD)->iptr; + gNB->num_pdsch_symbols_per_thread = *gpd(params, np, L1_NUM_TX_SYM_PER_THREAD)->iptr; gNB->TX_AMP = min(32767.0 / pow(10.0, .05 * (double)(*gpd(params, np, L1_TX_AMP_BACKOFF_dB)->uptr)), INT16_MAX); LOG_I(NR_PHY, "TX_AMP = %d (-%d dBFS)\n", gNB->TX_AMP, *gpd(params, np, L1_TX_AMP_BACKOFF_dB)->uptr); AssertFatal(gNB->TX_AMP > 300, "TX_AMP is too small, must be larger than 300 (is %d)\n", gNB->TX_AMP);