简体   繁体   中英

CPP function's execution duration follows bimodal distribution

Why does my C++ function's execution times follow a bimodal distribution?

In my C++ code, I load an external library, a data processor (either a cpp class compiled to a shared object which is dynamically loaded, or a python class), then call its method data_received N times and measure how much time it each execution of data_received took. So I instantiate the class whose method I call only once at the beginning before measuring anything. However, in both versions, the execution durations follow a bimodal distribution (Figure 1. cpp, Figure 2. python).

One thing to note here is that I'm running these functions as a callback whenever a ROS node receives a message. Publisher publishes a message with a frequency of 5000, so every 0.2 milliseconds. So these functions are called roughly once every 0.2 milliseconds.

In addition, I tried calling these functions simply 1000000 times normally, so without the callback. In this case, the execution duration distributions also follow this kind of bimodal distribution, but less strongly (Figure 3. and Figure 4.).

So there is a clear difference between whether I run the code normally sequentially or as a callback periodically. However, I don't understand why this should matter. Moreover, these durations seem to be periodic - so they come as groups. This is illustrated in Figure 5. This applies to both cpp and python and also when running the code normally, not as callbacks (but the effect is less clear).

I would guess that this is somehow related to CPU scheduling? However, I'm running on a Linux PREEMPT_RT kernel 5.15.55-rt48, have set the process priority to -98 and scheduling policy to SCHED_RR. I'm using Release build. I'm building the project with colcon colcon build --packages-select <ros package> --cmake-args -DCMAKE_BUILD_TYPE=Release and the following CMakeLists.txt. My compiler is GNU 9.4.0.

cmake_minimum_required(VERSION 3.8)
project(data_processor)

message(STATUS "compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")

if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    add_compile_options(-Wall -Wextra -Wpedantic)
endif ()

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(mtms_interfaces REQUIRED)
find_package(fpga_interfaces REQUIRED)

set(MATLAB_FIND_DEBUG true)
# MATLAB
find_package(Matlab)
if (Matlab_FOUND)
    # Following 5 lines taken from https://stackoverflow.com/questions/8880802/cmake-linking-shared-library
    # Fixes runtime error "error while loading shared libraries: libMatlabDataArray.so: cannot open shared object file: No such file or directory"
    SET(CMAKE_SKIP_BUILD_RPATH FALSE)
    SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
    SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib64")
    SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
    SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib64")

    set(LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:${Matlab_ROOT_DIR}/extern/bin/glnxa64:${Matlab_ROOT_DIR}/sys/os/glnxa64)
    include_directories(${Matlab_ROOT_DIR}/extern/include/)
    link_directories(${Matlab_ROOT_DIR}/extern/bin/glnxa64)
else ()
    message(STATUS "MATLAB NOT FOUND")
endif ()

add_executable(
        data_processor
        src/data_processor.cpp
        src/processor.cpp
        src/headers/processor.h
        src/python_processor.cpp
        src/matlab_processor.cpp
        src/compiled_matlab_processor.cpp
        src/matlab_processor_interface.cpp
        src/headers/matlab_processor.h
        src/headers/python_processor.h
        src/headers/compiled_matlab_processor.h
        src/headers/scheduling_utils.h
        src/headers/scheduling_utils.cpp
        src/headers/matlab_processor_interface.h
        src/headers/fpga_event.h
        src/headers/data_processor.h
        src/headers/matlab_helpers.h
        src/matlab_helpers.cpp)

target_include_directories(data_processor
        PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib>
        $<INSTALL_INTERFACE:lib>)

ament_target_dependencies(data_processor rclcpp std_msgs mtms_interfaces fpga_interfaces)

if (Matlab_FOUND)
    # MATLAB, Linker to libMatlabEngine in link_directories
    target_link_libraries(data_processor MatlabDataArray)
    target_link_libraries(data_processor MatlabEngine)
endif ()

# Python
find_package(PythonLibs)
if (PYTHONLIBS_FOUND)
    message(STATUS "Python found")
    include_directories(${PYTHON_INCLUDE_DIRS})
    target_link_libraries(data_processor ${PYTHON_LIBRARIES})
else ()
    message(STATUS "Python not found")
endif ()

install(TARGETS
        data_processor
        DESTINATION lib/${PROJECT_NAME}
        )

install(
        DIRECTORY launch
        DESTINATION share/${PROJECT_NAME}
)

if (BUILD_TESTING)
    find_package(ament_lint_auto REQUIRED)
    ament_lint_auto_find_test_dependencies()
endif ()

ament_package()

Figure 1. Callback durations in microseconds, cpp 图1。

Figure 2. Callback durations in microseconds, python 图 2。

Figure 3. Normal durations in microseconds, cpp 图 3。

Figure 4. Normal durations in microseconds, python 图 4。

Figure 5. Periodic durations in microseconds, python 图 5。

Compiling the dynamically loaded C++ library as a Release build fixed issues with C++. However, it still remains a question what causes the bimodality on the python version.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM