diff --git a/CMakeLists.txt b/CMakeLists.txt index d8b1a04a30..0a86eedd3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ project (OpenAirInterface LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 17) set(OAI_VERSION 2.4.0) -option(CUDA_ENABLE "Enable CUDA accelerated channel simulation" OFF) -if(CUDA_ENABLE) +option(ENABLE_CHANNEL_SIM_CUDA "Enable CUDA accelerated channel simulation" OFF) +if(ENABLE_CHANNEL_SIM_CUDA) find_package(CUDA REQUIRED) find_package(CUDAToolkit REQUIRED) message(STATUS "CUDA explicitly enabled, building with GPU acceleration support.") @@ -34,7 +34,7 @@ if(CUDA_ENABLE) message(STATUS "CUDA Explicit Copy path enabled (default ATS was overridden).") endif() - add_compile_definitions(ENABLE_CUDA) + add_compile_definitions(CHANNEL_SIM_CUDA) endif() ######################################################### @@ -2098,13 +2098,13 @@ target_link_libraries(nr_srssim PRIVATE m pthread ITTI dl nr_ue_phy_meas physim_common softmodem_common ) -if(CUDA_ENABLE) +if(ENABLE_CHANNEL_SIM_CUDA) if (TARGET oai_cuda_lib) target_link_libraries(nr_dlsim PRIVATE oai_cuda_lib) target_link_libraries(nr_ulsim PRIVATE oai_cuda_lib) - target_compile_definitions(nr_dlsim PRIVATE ENABLE_CUDA) - target_compile_definitions(nr_ulsim PRIVATE ENABLE_CUDA) + target_compile_definitions(nr_dlsim PRIVATE CHANNEL_SIM_CUDA) + target_compile_definitions(nr_ulsim PRIVATE CHANNEL_SIM_CUDA) endif() endif() diff --git a/ci-scripts/docker/Dockerfile.channelsim.ubuntu b/ci-scripts/docker/Dockerfile.channelsim.ubuntu index 73904c5fcb..cee8ccb66d 100644 --- a/ci-scripts/docker/Dockerfile.channelsim.ubuntu +++ b/ci-scripts/docker/Dockerfile.channelsim.ubuntu @@ -26,7 +26,7 @@ RUN cmake -GNinja -DENABLE_PHYSIM_TESTS=ON -DENABLE_TESTS=ON \ -DSANITIZE_UNDEFINED=OFF -DSANITIZE_ADDRESS=OFF \ -DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \ -DPHYSIM_CHECK_FILES="ThresholdsCuda.cmake" \ - -DCUDA_ENABLE=ON \ + -DENABLE_CHANNEL_SIM_CUDA=ON \ -DUSE_UNIFIED_MEMORY=ON \ -DUSE_ATS_MEMORY=OFF \ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/oai-ran/cmake_targets/ran_build/build \ diff --git a/ci-scripts/docker/Dockerfile.physim.cuda.ubuntu b/ci-scripts/docker/Dockerfile.physim.cuda.ubuntu index ef7928c0e6..f423ae72a3 100644 --- a/ci-scripts/docker/Dockerfile.physim.cuda.ubuntu +++ b/ci-scripts/docker/Dockerfile.physim.cuda.ubuntu @@ -26,7 +26,7 @@ RUN cmake -GNinja -DENABLE_PHYSIM_TESTS=ON -DENABLE_TESTS=ON \ -DSANITIZE_UNDEFINED=OFF -DSANITIZE_ADDRESS=OFF \ -DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \ -DPHYSIM_CHECK_FILES="ThresholdsCuda.cmake" \ - -DCUDA_ENABLE=ON \ + -DENABLE_CHANNEL_SIM_CUDA=ON \ -DUSE_UNIFIED_MEMORY=ON \ -DUSE_ATS_MEMORY=OFF \ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/oai-ran/cmake_targets/ran_build/build \ diff --git a/ci-scripts/docker/Dockerfile.unittest.cuda.ubuntu b/ci-scripts/docker/Dockerfile.unittest.cuda.ubuntu index d58e8887e2..c498b2aa8b 100644 --- a/ci-scripts/docker/Dockerfile.unittest.cuda.ubuntu +++ b/ci-scripts/docker/Dockerfile.unittest.cuda.ubuntu @@ -22,4 +22,4 @@ WORKDIR /oai-ran COPY . . WORKDIR /oai-ran/build -RUN cmake -GNinja -DENABLE_TESTS=ON -DCUDA_ENABLE=ON .. && ninja tests +RUN cmake -GNinja -DENABLE_TESTS=ON -DENABLE_CHANNEL_SIM_CUDA=ON .. && ninja tests diff --git a/openair1/PHY/TOOLS/tests/CMakeLists.txt b/openair1/PHY/TOOLS/tests/CMakeLists.txt index bd77e00c6a..4448422b50 100644 --- a/openair1/PHY/TOOLS/tests/CMakeLists.txt +++ b/openair1/PHY/TOOLS/tests/CMakeLists.txt @@ -48,19 +48,19 @@ target_link_libraries(benchmark_channel_pipeline PRIVATE UTIL SIMU PHY_COMMON LO add_executable(test_channel_pipeline test_channel_pipeline.cpp test_channel_pipeline_tools.c) target_link_libraries(test_channel_pipeline PRIVATE UTIL SIMU PHY_COMMON LOG CONFIG_LIB shlib_loader m channel_pipeline GTest::gtest thread-pool) -if (CUDA_ENABLE) - target_compile_definitions(test_channel_pipeline PRIVATE CUDA_ENABLE) +if (ENABLE_CHANNEL_SIM_CUDA) + target_compile_definitions(test_channel_pipeline PRIVATE CHANNEL_SIM_CUDA) add_dependencies(tests test_channel_pipeline) add_test(NAME test_channel_pipeline COMMAND test_channel_pipeline) set_tests_properties(test_channel_pipeline PROPERTIES LABELS "cuda") - target_compile_definitions(benchmark_channel_pipeline PRIVATE CUDA_ENABLE) + target_compile_definitions(benchmark_channel_pipeline PRIVATE CHANNEL_SIM_CUDA) add_dependencies(tests benchmark_channel_pipeline) add_test(NAME benchmark_channel_pipeline COMMAND benchmark_channel_pipeline) set_tests_properties(benchmark_channel_pipeline PROPERTIES LABELS "cuda") endif() -if(CUDA_ENABLE) +if (ENABLE_CHANNEL_SIM_CUDA) add_executable(test_multipath test_multipath.c) target_link_libraries(test_multipath PRIVATE UTIL SIMU LOG CONFIG_LIB shlib_loader m oai_cuda_lib) @@ -88,9 +88,9 @@ add_dependencies(tests test_channel_scalability) add_test(NAME test_channel_scalability COMMAND test_channel_scalability) if (TARGET oai_cuda_lib) - target_compile_definitions(test_multipath PRIVATE ENABLE_CUDA) - target_compile_definitions(test_noise PRIVATE ENABLE_CUDA) - target_compile_definitions(test_channel_simulation PRIVATE ENABLE_CUDA) - target_compile_definitions(test_channel_scalability PRIVATE ENABLE_CUDA) + target_compile_definitions(test_multipath PRIVATE CHANNEL_SIM_CUDA) + target_compile_definitions(test_noise PRIVATE CHANNEL_SIM_CUDA) + target_compile_definitions(test_channel_simulation PRIVATE CHANNEL_SIM_CUDA) + target_compile_definitions(test_channel_scalability PRIVATE CHANNEL_SIM_CUDA) endif() endif() diff --git a/openair1/PHY/TOOLS/tests/benchmark_channel_pipeline.cpp b/openair1/PHY/TOOLS/tests/benchmark_channel_pipeline.cpp index 681955aaa6..c69e5cf16a 100644 --- a/openair1/PHY/TOOLS/tests/benchmark_channel_pipeline.cpp +++ b/openair1/PHY/TOOLS/tests/benchmark_channel_pipeline.cpp @@ -25,7 +25,7 @@ extern "C" void exit_function(const char *file, const char *function, const int exit(EXIT_FAILURE); } -#ifdef CUDA_ENABLE +#ifdef CHANNEL_SIM_CUDA static void BM_channel_convolution_gpu(benchmark::State &state) { int nb_rx = state.range(0); @@ -203,7 +203,7 @@ static void BM_channel_convolution_tpool(benchmark::State &state) } } -#ifdef CUDA_ENABLE +#ifdef CHANNEL_SIM_CUDA BENCHMARK(BM_channel_convolution_gpu) ->ArgsProduct({ {1, 2, 4, 16, 64}, // nb_rx diff --git a/openair1/PHY/TOOLS/tests/test_channel_pipeline.cpp b/openair1/PHY/TOOLS/tests/test_channel_pipeline.cpp index e4b8d2cdf9..2112019e3b 100644 --- a/openair1/PHY/TOOLS/tests/test_channel_pipeline.cpp +++ b/openair1/PHY/TOOLS/tests/test_channel_pipeline.cpp @@ -26,7 +26,7 @@ class ChannelConvolutionTest : public ::testing::TestWithParam(GetParam()); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 75009e1ac5..427f5e0cec 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -73,7 +73,7 @@ #define inMicroS(a) (((double)(a))/(get_cpu_freq_GHz()*1000.0)) #include "SIMULATION/LTE_PHY/common_sim.h" -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA #include #include "SIMULATION/TOOLS/oai_cuda.h" #endif @@ -397,7 +397,7 @@ int main(int argc, char **argv) void *h_tx_sig_pinned = NULL; -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA void *d_tx_sig = NULL, *d_intermediate_sig = NULL, *d_final_output = NULL; void *d_curand_states = NULL; void *h_final_output_pinned = NULL; @@ -413,7 +413,7 @@ int main(int argc, char **argv) printf("handling optarg %c\n",c); switch (c) { case 'f': -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA if (strcmp(optarg, "cuda") == 0) { use_cuda = 1; } else @@ -638,7 +638,7 @@ int main(int argc, char **argv) printf("-d number of dlsch threads, 0: no dlsch parallelization\n"); printf("-e MSC index\n"); printf("-f Enable optional feature flag. Available flags:\n"); -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA printf(" cuda Enable CUDA channel simulation\n"); #else printf(" (none) No optional features were compiled into this executable\n"); @@ -680,7 +680,7 @@ int main(int argc, char **argv) /* initialize the sin table */ InitSinLUT(); -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA init_cuda_chsim_buffers(use_cuda, n_tx, n_rx, @@ -693,7 +693,7 @@ int main(int argc, char **argv) &d_channel_coeffs_gpu); #endif -#if !defined(ENABLE_CUDA) || !use_cuda +#if !defined(CHANNEL_SIM_CUDA) || !use_cuda printf("Pre-allocating padded host memory for the CPU channel pipeline...\n"); int num_samples_alloc = 153600; const int max_padding_alloc = 256 - 1; @@ -872,7 +872,7 @@ int main(int argc, char **argv) 0, 0); -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA float *h_channel_coeffs = NULL; if (use_cuda) { int num_links = n_tx * n_rx; @@ -1219,7 +1219,7 @@ int main(int argc, char **argv) } // Apply MIMO Channel -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA if (use_cuda) { #if defined(USE_UNIFIED_MEMORY) int deviceId; @@ -1518,7 +1518,7 @@ int main(int argc, char **argv) free(r_im[i]); } -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA free_cuda_chsim_buffers(use_cuda, &d_tx_sig, &d_intermediate_sig, diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 368cccfbce..c1a8a25d7e 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -74,7 +74,7 @@ #include "time_meas.h" #include "utils.h" -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA #include #include "SIMULATION/TOOLS/oai_cuda.h" #endif @@ -357,7 +357,7 @@ int main(int argc, char *argv[]) void *h_tx_sig_pinned = NULL; -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA void *d_tx_sig = NULL, *d_intermediate_sig = NULL, *d_final_output = NULL; void *d_curand_states = NULL; void *h_final_output_pinned = NULL; @@ -398,7 +398,7 @@ int main(int argc, char *argv[]) break; case 'f': -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA if (strcmp(optarg, "cuda") == 0) { use_cuda = 1; } else @@ -670,7 +670,7 @@ int main(int argc, char *argv[]) printf("-d Introduce delay in terms of number of samples\n"); printf("-e To simulate MSG3 configuration\n"); printf("-f Enable optional feature flag. Available flags:\n"); -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA printf(" cuda Enable CUDA channel simulation\n"); #else printf(" (none) No optional features were compiled into this executable\n"); @@ -894,7 +894,7 @@ int main(int argc, char *argv[]) } const int num_samples_alloc = 153600; -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA init_cuda_chsim_buffers(use_cuda, n_tx, n_rx, @@ -911,7 +911,7 @@ int main(int argc, char *argv[]) } #endif -#if !defined(ENABLE_CUDA) || !use_cuda +#if !defined(CHANNEL_SIM_CUDA) || !use_cuda printf("Pre-allocating padded host memory for the CPU channel pipeline...\n"); const int max_padding_alloc = 256 - 1; size_t padded_tx_alloc_bytes = n_tx * (num_samples_alloc + max_padding_alloc) * 2 * sizeof(float); @@ -1481,7 +1481,7 @@ int main(int argc, char *argv[]) memcpy(data_start_ptr, s_interleaved[j], slot_length * 2 * sizeof(float)); } -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA if (use_cuda) { #if defined(USE_UNIFIED_MEMORY) int deviceId; @@ -1921,7 +1921,7 @@ int main(int argc, char *argv[]) fclose(uci_ulsch_matlab_vec); free_and_zero(UE->phy_sim_test_buf); -#ifdef ENABLE_CUDA +#ifdef CHANNEL_SIM_CUDA free_cuda_chsim_buffers(use_cuda, &d_tx_sig, &d_intermediate_sig, diff --git a/openair1/SIMULATION/TOOLS/CMakeLists.txt b/openair1/SIMULATION/TOOLS/CMakeLists.txt index 4ea2d2373c..baa302bab3 100644 --- a/openair1/SIMULATION/TOOLS/CMakeLists.txt +++ b/openair1/SIMULATION/TOOLS/CMakeLists.txt @@ -3,17 +3,16 @@ add_library(noise_device noise_device.c) target_link_libraries(noise_device PRIVATE log_headers SIMU) target_include_directories(noise_device PUBLIC ./) -set(CHANNEL_PIPELINE_SOURCES channel_pipeline.c) -if (CUDA_ENABLE) - list(APPEND CHANNEL_PIPELINE_SOURCES channel_pipeline_v2.cu) +add_library(channel_pipeline channel_pipeline.c) +if (ENABLE_CHANNEL_SIM_CUDA) + target_sources(channel_pipeline PRIVATE channel_pipeline_v2.cu) endif() -add_library(channel_pipeline ${CHANNEL_PIPELINE_SOURCES}) target_link_libraries(channel_pipeline PUBLIC thread-pool noise_device) -if (CUDA_ENABLE) +if (ENABLE_CHANNEL_SIM_CUDA) target_link_libraries(channel_pipeline PUBLIC CUDA::toolkit) endif() -if(CUDA_ENABLE) +if(ENABLE_CHANNEL_SIM_CUDA) add_library(oai_cuda_lib STATIC multipath_channel.cu phase_noise.cu diff --git a/openair1/SIMULATION/TOOLS/DOC/gpu_acceleration.md b/openair1/SIMULATION/TOOLS/DOC/gpu_acceleration.md index 5205b8aea6..1450245234 100644 --- a/openair1/SIMULATION/TOOLS/DOC/gpu_acceleration.md +++ b/openair1/SIMULATION/TOOLS/DOC/gpu_acceleration.md @@ -132,9 +132,9 @@ This is the traditional CUDA programming model. The host and device have separat ## Project Integration -To ensure the feature is modular, the integration into the OAI project was handled at both the build system and source code levels. All of the new CUDA source files (`channel_pipeline.cu`, `multipath_channel.cu`, `phase_noise.cu`) are compiled into a single static library named `oai_cuda_lib`. This is defined in the main `CMakeLists.txt` file and is controlled by the `CUDA_ENABLE` CMake option, which is disabled by default. When this option is activated (`-DCUDA_ENABLE=ON`), the build system compiles the CUDA library and also defines a global `ENABLE_CUDA` preprocessor macro that is visible to the rest of the project. +To ensure the feature is modular, the integration into the OAI project was handled at both the build system and source code levels. All of the new CUDA source files (`channel_pipeline.cu`, `multipath_channel.cu`, `phase_noise.cu`) are compiled into a single static library named `oai_cuda_lib`. This is defined in the main `CMakeLists.txt` file and is controlled by the `ENABLE_CHANNEL_SIM_CUDA` CMake option, which is disabled by default. When this option is activated (`-DENABLE_CHANNEL_SIM_CUDA=ON`), the build system compiles the CUDA library and also defines a global `CHANNEL_SIM_CUDA` preprocessor macro that is visible to the rest of the project. -This `ENABLE_CUDA` macro is then used within the simulator files, such as `dlsim.c` and `ulsim.c`, to conditionally compile all CUDA-related code. This approach allows for the inclusion of the `oai_cuda.h` header, and the pre-allocation of GPU memory at startup, all without affecting the standard CPU-only build. +This `CHANNEL_SIM_CUDA` macro is then used within the simulator files, such as `dlsim.c` and `ulsim.c`, to conditionally compile all CUDA-related code. This approach allows for the inclusion of the `oai_cuda.h` header, and the pre-allocation of GPU memory at startup, all without affecting the standard CPU-only build. Inside the main processing loop, an `if (use_cuda)` statement acts as the primary runtime switch. To enable a direct comparison, timing measurement calls have been added to both the GPU and CPU execution paths. Also, both paths now source their data from the same common, pre-padded host buffer. The GPU path receives a pointer to the entire padded buffer and leverages its optimized kernel, while the CPU path uses a temporary array of offset pointers to work on the same data without being aware of the padding. This ensures both computations operate on the exact same source data, isolating the performance measurement to the channel processing itself. To execute the simulation on the GPU, the `-f cuda` flag must be provided at runtime; otherwise, the program defaults to this refined CPU implementation. diff --git a/openair1/SIMULATION/TOOLS/channel_pipeline.h b/openair1/SIMULATION/TOOLS/channel_pipeline.h index fc8d9e29c0..c915f31521 100644 --- a/openair1/SIMULATION/TOOLS/channel_pipeline.h +++ b/openair1/SIMULATION/TOOLS/channel_pipeline.h @@ -10,7 +10,7 @@ extern "C" { #endif #include "common/platform_types.h" -#ifdef CUDA_ENABLE +#ifdef CHANNEL_SIM_CUDA void *cuda_channel_pipeline_init(int max_samples); void cuda_channel_pipeline_shutdown(void *context_handle); void cuda_channel_pipeline(void *context_handle, diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index 65bb102874..005f0a6394 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -439,7 +439,7 @@ endif() ###### cuda-specific tests ###### #################################################################################### -if (CUDA_ENABLE) +if (ENABLE_CHANNEL_SIM_CUDA) # --- Test Suite 1: 61440 samples, 2/4/8/32 TX - 2/4/8/32 RX --- add_physim_test(cuda.5g.channelsim.test_channel_scalability.test1 "16 channels 61440 samples 2T2R Batch" test_channel_scalability -c 16 -t 2 -r 2 -s 61440 -l 32 -m batch -n 12) diff --git a/radio/vrtsim/CMakeLists.txt b/radio/vrtsim/CMakeLists.txt index b60c955f72..687bd13566 100644 --- a/radio/vrtsim/CMakeLists.txt +++ b/radio/vrtsim/CMakeLists.txt @@ -22,9 +22,8 @@ target_link_libraries(vrtsim channel_pipeline thread-pool ) -if (CUDA_ENABLE) - target_compile_definitions(vrtsim PRIVATE CUDA_ENABLE) - target_compile_definitions(vrtsim PRIVATE CUDA_ENABLE) +if (ENABLE_CHANNEL_SIM_CUDA) + target_compile_definitions(vrtsim PRIVATE CHANNEL_SIM_CUDA) endif() # Optional taps client diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index cb67815fa4..9bce6a7124 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -678,7 +678,7 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state, } size_t saved_samples_input_len = channel_length - 1; - #ifdef CUDA_ENABLE + #ifdef CHANNEL_SIM_CUDA cuda_channel_pipeline(vrtsim_state->channel_pipeline_context, (const cf_t **)channel_impulse_response_p, (const c16_t **)saved_samples_ptr, @@ -885,7 +885,7 @@ static void vrtsim_end(openair0_device_t *device) tx_timing_t *tx_timing = &vrtsim_state->tx_timing; if (vrtsim_state->chanmod || vrtsim_state->taps_socket || vrtsim_state->use_cirdb) { -#ifdef CUDA_ENABLE +#ifdef CHANNEL_SIM_CUDA cuda_channel_pipeline_shutdown(vrtsim_state->channel_pipeline_context); #else abortTpool(&vrtsim_state->tpool); @@ -988,7 +988,7 @@ __attribute__((__visibility__("default"))) int device_init(openair0_device_t *de int noise_power_dBFS = get_noise_power_dBFS(); int16_t noise_power = noise_power_dBFS == INVALID_DBFS_VALUE ? 0 : (int16_t)(32767.0 / powf(10.0, .05 * -noise_power_dBFS)); LOG_A(HW, "VRTSIM: Noise power %d sample value\n", noise_power); -#ifdef CUDA_ENABLE +#ifdef CHANNEL_SIM_CUDA size_t samples_in_one_ms = openair0_cfg->sample_rate / 1000 / 1000; vrtsim_state->channel_pipeline_context = cuda_channel_pipeline_init(openair0_cfg->tx_num_channels * samples_in_one_ms); #else