Commit 97dc9997 authored by mir's avatar mir

Fist commit

parent ef06b145
......@@ -244,7 +244,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb2 -Wl,-rpath -Wl,${C
# these changes are related to hardcoded path to include .h files
set(debugOpt "-ggdb2 -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks")
set(CMAKE_C_FLAGS_DEBUG "${debugOpt} -O0")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${debugOpt} -O2")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${debugOpt} -O3")
set(CMAKE_C_FLAGS_RELEASE "-O3")
# Enable assert() for RelWithDebInfo builds
......@@ -2230,6 +2230,8 @@ add_executable(nr-softmodem
${nr_rrc_h}
${s1ap_h}
# ${OPENAIR_BIN_DIR}/messages_xml.h
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR_DIR}/executables/nr-gnb.c
${OPENAIR_DIR}/executables/nr-ru.c
${OPENAIR_DIR}/executables/nr-softmodem.c
......@@ -2401,6 +2403,7 @@ target_link_libraries(ldpctest PRIVATE
)
add_executable(nr_dlschsim
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
......@@ -2461,6 +2464,7 @@ target_link_libraries(nr_dlsim PRIVATE
target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_prachsim
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/prachsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
......@@ -2486,6 +2490,7 @@ target_link_libraries(nr_ulschsim PRIVATE
target_link_libraries(nr_ulschsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_ulsim
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
......
Thread Pool implemented in C following the talk of Sean Parent "Better Code: Concurrency" from 2016
#include <assert.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "task_manager.h"
#define NUM_THREADS 4
#define NUM_JOBS 1024
int64_t time_now_us(void)
{
struct timespec tms;
/* The C11 way */
/* if (! timespec_get(&tms, TIME_UTC)) */
/* POSIX.1-2008 way */
if (clock_gettime(CLOCK_MONOTONIC_RAW,&tms)) {
return -1;
}
/* seconds, multiplied with 1 million */
int64_t micros = tms.tv_sec * 1000000;
/* Add full microseconds */
int64_t const tv_nsec = tms.tv_nsec;
micros += tv_nsec/1000;
/* round up if necessary */
if (tv_nsec % 1000 >= 500) {
++micros;
}
return micros;
}
typedef struct{
int64_t a;
int64_t time;
} pair_t;
static inline
int64_t naive_fibonnacci(int64_t a)
{
assert(a < 1000);
if(a < 2)
return a;
return naive_fibonnacci(a-1) + naive_fibonnacci(a-2);
}
//static _Thread_local int64_t counter = 0;
static
int marker_fd;
void do_work(void* arg)
{
int64_t now = time_now_us();
pair_t* a = (pair_t*)arg;
naive_fibonnacci(23 + a->a);
int64_t stop = time_now_us();
char buffer[100] = {0};
int ret = snprintf(buffer, 100, "ID %lu Fib elapsed %ld start-stop %ld - %ld \n", pthread_self(), stop - now, now, stop);
assert(ret > 0 && ret < 100);
// write_marker_ft_mir(marker_fd, buffer);
// puts(buffer);
}
int main()
{
task_manager_t man = {0};
init_task_manager(&man, NUM_THREADS);
usleep(100);
pair_t* arr = calloc(NUM_JOBS, sizeof(pair_t));
assert(arr != NULL);
int64_t now = time_now_us();
for(int k = 0; k < NUM_JOBS/8; ++k){
for(int i = 0; i < 8; ++i){
pair_t* pa = &arr[i];
pa->a = 0; //i%10;
pa->time = 0;
task_t t = {.args = pa, t.func = do_work};
async_task_manager(&man, t);
}
printf("Waiting %ld \n", time_now_us());
trigger_and_wait_all_task_manager(&man);
printf("Done %ld \n", time_now_us());
//usleep(1024);
}
free_task_manager(&man, NULL);
printf("Total elapsed %ld \n", time_now_us() - now);
free(arr);
return EXIT_SUCCESS;
}
#!/bin/bash
# Full dyntick CPU on which we'll run the user loop,
# it must be part of nohz_full kernel parameter
TARGET=4
# Migrate all possible tasks to CPU 0
for P in $(ls /proc)
do
if [ -x "/proc/$P/task/" ]
then
echo $P
taskset -acp 0 $P
fi
done
# Migrate irqs to CPU 0
for D in $(ls /proc/irq)
do
if [[ -x "/proc/irq/$D" && $D != "0" ]]
then
echo $D
echo 1 > /proc/irq/$D/smp_affinity
fi
done
# Delay the annoying vmstat timer far away
sysctl vm.stat_interval=120
# Shutdown nmi watchdog as it uses perf events
sysctl -w kernel.watchdog=0
# Remove -rt task runtime limit
echo -1 > /proc/sys/kernel/sched_rt_runtime_us
# Pin the writeback workqueue to CPU0
echo 1 > /sys/bus/workqueue/devices/writeback/cpumask
DIR=/sys/kernel/debug/tracing
echo > $DIR/trace
echo 0 > $DIR/tracing_on
# Uncomment the below for more details on what disturbs the CPU
echo 0 > $DIR/events/irq/enable
echo 1 > $DIR/events/sched/sched_switch/enable
echo 1 > $DIR/events/workqueue/workqueue_queue_work/enable
echo 1 > $DIR/events/workqueue/workqueue_execute_start/enable
echo 1 > $DIR/events/timer/hrtimer_expire_entry/enable
echo 1 > $DIR/events/timer/tick_stop/enable
echo nop > $DIR/current_tracer
echo 1 > $DIR/tracing_on
# Run a 10 secs user loop on target
taskset -c 3-7 ./a.out
#sleep 20
#killall a.out
# Checkout the trace in trace.* file
cat /sys/kernel/debug/tracing/per_cpu/cpu4/trace > trace.4
cat /sys/kernel/debug/tracing/per_cpu/cpu5/trace > trace.5
cat /sys/kernel/debug/tracing/per_cpu/cpu6/trace > trace.6
cat /sys/kernel/debug/tracing/per_cpu/cpu7/trace > trace.7
#ifndef TASK_WORK_STEALING_THREAD_POOL_H
#define TASK_WORK_STEALING_THREAD_POOL_H
typedef struct{
void* args;
void (*func)(void* args);
} task_t;
#endif
This diff is collapsed.
#ifndef TASK_MANAGER_WORKING_STEALING_H
#define TASK_MANAGER_WORKING_STEALING_H
// Comment for deactivating ws tpool
//#define TASK_MANAGER
#include "task.h"
#include <pthread.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
typedef struct{
pthread_t* t_arr;
size_t len_thr;
atomic_uint_fast64_t index;
void* q_arr;
atomic_uint_fast64_t num_task;
pthread_cond_t wait_cv;
pthread_mutex_t wait_mtx;
_Atomic int32_t futex;
_Atomic bool waiting;
} task_manager_t;
void init_task_manager(task_manager_t* man, uint32_t num_threads);
void free_task_manager(task_manager_t* man, void (*clean)(task_t* args) );
void async_task_manager(task_manager_t* man, task_t t);
void trigger_and_spin(task_manager_t* man);
void trigger_and_wait_all_task_manager(task_manager_t* man);
void wait_all_task_manager(task_manager_t* man);
#endif
......@@ -44,6 +44,9 @@
#include "executables/rt_profiling.h"
#include "nfapi_nr_interface_scf.h"
#include "common/utils/thread_pool/task_manager.h"
#define MAX_NUM_RU_PER_gNB 8
#define MAX_PUCCH0_NID 8
......@@ -778,6 +781,11 @@ typedef struct PHY_VARS_gNB_s {
void *scopeData;
/// structure for analyzing high-level RT measurements
rt_L1_profiling_t rt_L1_profiling;
#ifdef TASK_MANAGER
task_manager_t man;
#endif
} PHY_VARS_gNB;
typedef struct LDPCDecode_s {
......
......@@ -39,6 +39,8 @@
#include "executables/softmodem-common.h"
#include "nfapi/oai_integration/vendor_ext.h"
#include "NR_SRS-ResourceSet.h"
#include "common/utils/thread_pool/task_manager.h"
#include "assertions.h"
......@@ -232,9 +234,15 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,0);
}
#ifdef TASK_MANAGER
void nr_postDecode(PHY_VARS_gNB *gNB, ldpcDecode_t *rdata)
{
#else
void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
{
ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
#endif
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
NR_gNB_ULSCH_t *ulsch = rdata->ulsch;
int r = rdata->segment_r;
......@@ -252,6 +260,8 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
} else {
if ( rdata->nbSegments != ulsch_harq->processedSegments ) {
// Let's forget about this optimization for now
#ifndef TASK_MANAGER
int nb = abortTpoolJob(&gNB->threadPool, req->key);
nb += abortNotifiedFIFOJob(&gNB->respDecode, req->key);
gNB->nbDecode-=nb;
......@@ -260,6 +270,7 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n",
ulsch_harq->processedSegments, nb, rdata->nbSegments);
ulsch_harq->processedSegments=rdata->nbSegments;
#endif
}
}
......@@ -350,6 +361,12 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid)
{
#ifdef TASK_MANAGER
trigger_and_spin(&gNB->man);
#endif
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu;
......@@ -408,15 +425,19 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH
start_meas(&gNB->ulsch_decoding_stats);
nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G);
#ifndef TASK_MANAGER
if (enable_ldpc_offload == 0) {
while (gNB->nbDecode > 0) {
notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool);
if (req == NULL)
break; // Tpool has been stopped
break; // Tpool has been stopped
nr_postDecode(gNB, req);
delNotifiedFIFO_elt(req);
}
}
#endif
stop_meas(&gNB->ulsch_decoding_stats);
}
......
......@@ -67,6 +67,8 @@
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "executables/nr-uesoftmodem.h"
#include "common/utils/thread_pool/task_manager.h"
//#define DEBUG_ULSIM
const char *__asan_default_options()
......@@ -586,6 +588,10 @@ int main(int argc, char **argv)
gNB->ofdm_offset_divisor = UINT_MAX;
initNotifiedFIFO(&gNB->respDecode);
#ifdef TASK_MANAGER
init_task_manager(&gNB->man, threadCnt);
#endif
initFloatingCoresTpool(threadCnt, &gNB->threadPool, false, "gNB-tpool");
initNotifiedFIFO(&gNB->respDecode);
initNotifiedFIFO(&gNB->L1_tx_free);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment