减少唤醒延迟/响应时间 std::condition_variable::wait_for

问题描述 投票:0回答:1

操作系统:vxWorks 7 23.09
C++17
编译器:Clang
硬件平台:Intel第11代i7 CPU
BSP:英特尔通用 BSP 64 位

我有 2 个线程。其中一个线程称为以太网读取器线程,顾名思义,它从套接字读取数据并将其推送到 std::queue 并通知主线程(处理线程)。
主线程(处理线程)在没有数据要处理时使用

std::condition_variable::wait_for
来让出 CPU。之前我使用忙等待设计模式进行处理。

enter image description here

我希望减少使用

std::condition_variable::wait_for
时唤醒线程/任务的延迟。

早些时候,当我不使用

std::condition_variable::wait_for
时,即在无限循环内使用忙等待设计模式时,我处理以太网数据的整个处理时间为 3-15 微秒。

当我使用

std::condition_variable::wait_for
时,处理线程需要 50-250 微秒才能唤醒。其余处理在 15 微秒内完成。
看起来问题的解决方案(忙等待)比问题的成本更昂贵。

如果我将处理线程让出 CPU,以防没有数据要处理,我正在寻找减少唤醒延迟的策略。
我并不专注于

std::condition_variable::wait_for
,如果有其他方法提供更好的延迟/响应时间,我准备改变我的方法。

输出:

Calling Notify All : 1731492554671893
Inside Wait For : 1731492554672106
Calling Notify All : 1731492557672289
Inside Wait For : 1731492557672506
Calling Notify All : 1731492560672740
Inside Wait For : 1731492560672901

代码:

wait_for_event.hpp

#include <mutex>
#include <chrono>
#include <iostream>
#include <optional>
#include <condition_variable>

namespace wfe
{
    enum class WaitForEventStatus : std::uint8_t
    {
        Error = 0,
        Timeout,
        NoTimeout,
        NoError  //Required for just wait
    };

    class WaitForEvent
    {
    private:
        std::mutex              mutex;
        std::condition_variable condition_variable;
    public:

        void notify_one(void) noexcept
        {
            this->condition_variable.notify_one();
        }

        void notify_all(void) noexcept
        {
            this->condition_variable.notify_all();
        }

        void wait(void)
        {
            std::unique_lock<std::mutex> lock(this->mutex);
            this->condition_variable.wait(lock);
        }

        template <class Rep, class Period>
        WaitForEventStatus wait_for(const std::chrono::duration<Rep,Period>& wait_time)
        {
            try
            {
                std::unique_lock<std::mutex> lock(this->mutex);
                auto return_status = this->condition_variable.wait_for(lock, wait_time);
                if(return_status == std::cv_status::no_timeout)
                {
                    return WaitForEventStatus::NoTimeout;
                }
                else
                {
                    return WaitForEventStatus::Timeout;
                }
            }
            catch(const std::exception& e)
            {
                std::cerr << e.what() << '\n';
                return WaitForEventStatus::Error;
            }
        }

        template <class Clock, class Duration>
        WaitForEventStatus wait_until(const std::chrono::time_point<Clock,Duration>& abs_time)
        {
            try
            {
                std::unique_lock<std::mutex> lock(this->mutex);
                auto return_status = this->condition_variable.wait_until(lock, abs_time);
                if(return_status == std::cv_status::no_timeout)
                {
                    return WaitForEventStatus::NoTimeout;
                }
                else
                {
                    return WaitForEventStatus::Timeout;
                }
            }
            catch(const std::exception& e)
            {
                std::cerr << e.what() << '\n';
                return WaitForEventStatus::Error;
            }
        }

        WaitForEvent() = default;
        ~WaitForEvent() = default;
    };
}

主.cpp

#include <mutex>
#include <thread>
#include <chrono>
#include <iostream>
#include <condition_variable>
#include "wait_for_event.hpp"

wfe::WaitForEvent event;

void thread_runner(void)
{
    while (true)
    {
        // Code to read data from socket and push the data in queue
        std::this_thread::sleep_for (std::chrono::seconds(3));//Only for testing - not on live code
        std::cout << "Calling Notify All : " << std::chrono::duration_cast<std::chrono::microseconds>
            (std::chrono::system_clock::now().time_since_epoch()).count() << std::endl;
        event.notify_all();
    }
}

int main(int argc, char const *argv[])
{
    std::thread t {thread_runner};
    while (true)
    {
        auto return_status = event.wait_for(std::chrono::seconds(1));
        if(return_status == wfe::WaitForEventStatus::Timeout)
        {
            //std::cout << "WaitForEventStatus::Timeout\n";
        }
        else if(return_status == wfe::WaitForEventStatus::NoTimeout)
        {
            //std::cout << "WaitForEventStatus::NoTimeout\n";
            std::cout << "Inside Wait For : " << std::chrono::duration_cast<std::chrono::microseconds>
            (std::chrono::system_clock::now().time_since_epoch()).count() << std::endl;
        }
    }
    
    return 0;
}
c++ c multithreading real-time vxworks
1个回答
0
投票

我认为实现极低延迟的唯一方法是使用软件中断。

另一种选择是使用更轻量的同步原语,例如二进制信号量

事件标志(eventLib)也很高效。

© www.soinside.com 2019 - 2024. All rights reserved.