CPU Auslastung bei zyklischem Aufruf einer Funktion.



  • Hallo zusammen.
    Um eine Funktion zyklisch aufzurufen habe ich im Netz nach Hilfe gesucht und bin auf folgendes gestoßen:

    https://stackoverflow.com/questions/30425772/c-11-calling-a-c-function-periodically

    Dazu benötige ich noch eine ConcurrentQueue.
    Dazu habe ich folgende lib verwendet:

    https://github.com/cameron314/concurrentqueue

    Mein Projekt habe ich in Visual Studio 2017 implementiert.
    Das Programm hat eine CPU Auslastung von 13%. Was ich für ziemlich hoch halte.
    Und das ist auch der Grund für der Thread hier.

    Fragen:
    Kann ich die Auslastung irgendwie senken?
    Irgendwas optimieren?
    Habe ich was falsch gemacht?
    Oder meint ihr Auslastung ist normal?

    Mein Code sieht wie folg aus: (Testprojekt)

    FunctionItem.h (auszuführende Funktion muss für Auswertungszwecke mit einem Namen versehen werden)

    #pragma once
    
    #include <functional>
    
    class FunctionItem
    {
        std::function<void()> _func;
        std::string_view _name{};
    
    public:
    
        explicit FunctionItem(std::function<void()> func, const std::string_view name="") 
                            : _func(std::move(func)), _name(name)
        {
        }
    
        FunctionItem() = default;
        virtual ~FunctionItem() = default;
        FunctionItem(const FunctionItem& other) = default;
        FunctionItem(FunctionItem&& other) noexcept = default;
        FunctionItem& operator=(const FunctionItem& other) = default;
        FunctionItem& operator=(FunctionItem&& other) noexcept = default;
    
        const std::function<void()>& Func() const
        {
            return _func;
        }
    };
    

    ConsumerThread.h
    hier abgeschaut
    // https://stackoverflow.com/questions/30425772/c-11-calling-a-c-function-periodically
    und angepasst

    #pragma once
    
    #include "FunctionItem.h"
    #include <functional>
    #include <thread>
    #include <atomic>
    #include "concurrentqueue.h"
    
    using namespace moodycamel;
    using namespace std;
    
    class ConsumerThread
    {
        shared_ptr<ConcurrentQueue<FunctionItem>> _queue;
    
        thread _thread;
        atomic<bool> _run;
    
    public:
    
        ConsumerThread(): 
            _queue(nullptr), 
            _run(false)
        {   
        }
    
        ~ConsumerThread()
        {
            if(_run.load(memory_order_acquire))
            {
                Stop();
            }
        }
    
        std::thread Start(const shared_ptr<ConcurrentQueue<FunctionItem>>& queue)
        {
            if (_run.load(memory_order_acquire))
            {
                Stop();
            }
    
            _run.store(true, memory_order_release);
    
            _queue = queue;
    
            _thread = thread(&ConsumerThread::Run, this);
    
            return std::move(_thread);
        }
    
        void Stop()
        {
            _run.store(false, memory_order_release);
    
            if (_thread.joinable())
                _thread.join();
    
        }
    
        bool IsRunning() const noexcept
        {
            return _run.load(memory_order_acquire) &&
                   _thread.joinable();
        }
    
    
    private:
    
        void Run() const
        {
            FunctionItem item;
    
            while (_run.load(memory_order_acquire))
            {
                if (_queue->try_dequeue(item))
                {
                    item.Func()();
                }	
            }
        }
    };
    

    main

    
    #include <iostream>
    #include "ConsumerThread.h"
    
    int main()
    {
       ConsumerThread thread;
    
        auto queue = make_shared<ConcurrentQueue<FunctionItem>>();
    
        auto th = thread.Start(queue);
    
         //queue->enqueue(FunctionItem([&]() // tut erst mal nichts zu Sache
         //{
         //    std::cout << "run" << std::endl;
         //}, "RUN"));
    
        th.join();    
    }
    


  • Du hast in deiner Run-Funktion ja auch eine Dauerschleife. Verwende dort zumindestens sleep_for mit einigen Millisekunden.

    Oder aber du nutzt gleich eine der blockierenden wait_dequeue-Überladungen (evtl. mit Timer, falls du doch noch andere Aktionen periodisch in der Funktion ausführen möchtest) - lies dir einfach mal den Abschnitt Blocking version durch.



  • Hi Th69

    Danke für deine Antwort. Habe mal auf die Blocking Version umgebaut.
    Nun habe ich ne Speicherauslastung von 0% 🙂

    Aber wenn ich nun meine Funktion einreihe wird die nicht mehr ausgeführt. Habe wohl noch was nicht verstanden bzw falsch gemacht.

    Also habe im gezeigten Code die ConcurrentQueue durch eine BlockingConcurrentQueue ersetzt
    und die Run Methode wie folgt umgebaut:

    void Run() const
    {
        while (_run.load(memory_order_acquire))
        {
            FunctionItem item;
    
            _queue->wait_dequeue(item);
    
            if (_queue->wait_dequeue_timed(item, std::chrono::milliseconds(5))) 
            {
                item.Func()();
            }
        }
    }
    

    und in der Main den Teil mit dem enqueue aktiviert:

    queue->enqueue(FunctionItem([&]() 
    {
        std::cout << "run" << std::endl;
    }, "RUN"));
    

    jetzt hätte ich eigentlich erwartet das run in der Ausgabe erscheint.



  • Das liegt daran dass ich

    entweder wait_dequeue oder wait_dequeue_timed aufrufen muss. 😏


Log in to reply