非阻塞pthread停止-或为什么std :: atomic_flag减慢我的代码的速度 [英] Non-blocking pthread stop - or why does std::atomic_flag slow down my code

查看:186
本文介绍了非阻塞pthread停止-或为什么std :: atomic_flag减慢我的代码的速度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实现了一个小多线程应用程序,该应用程序执行以下操作:

I implemented a little multithreaded application which does the following:

MainThread

主线程使用setitimer启动计时器,并最多启动8个计时器 线程.来自主线程的计时器用于从>一个文件(每0.25s)中重复读取.当计时器被调用20次(约5秒后)时,我 想要停止线程并获得计算量 每个线程.

A main thread starts a timer using setitimer and starts up to 8 threads. The timer from the main thread is used to read repeatedly from > a file (every 0.25s). When the timer is called 20 times (after ~5s), I want to stop the threads and get the amount of computations done by every thread.

MainThread.h

MainThread.h

class MainThread {
  private:
    int counter;
    ThreadManager tm;
    bool registerTimer(double seconds);
    void startTimerWithInterval(double interval);
    void read() {
      /**
       *  If counter >= 20, call stopWorker on all threads
       */
      tm.stopWorkers();
    }
  public:
    MainThread():counter(0){}
}

WorkerThreads

在无限循环中执行一些昂贵的计算. 经过一定数量的计算后,线程必须存储 它执行的计算数量.该值(计算量) 必须非常准确,所以我认为我必须停止线程(非常) 立即.

Perform some expensive computations whithin an infinity loop. After a certain amount of computations, the thread has to store the number of computations it performed. This value (amount of computations) has to be quite accurate, so i think I have to stop the threads (quite) immediatly.

ThreadClass.h

ThreadClass.h

class WorkerThread { 
  private:
    /**
     * ...
     */
    std::atomic_flag keep_Running = ATOMIC_FLAG_INIT;

    static void* run(void* args) {
      ((WorkerThread*)args)->process();
      pthread_exit(nullptr);
      return nullptr;
    }

  public:
    /**
     * ...
     */
    bool startWorker() {
      keep_Running.test_and_set();
      bool result = (pthread_create(&thread, pthread_attr, run, this) == 0);
      if(!result) {
        keep_Running.clear();
      }
      return result;
    }
    void stopWorker() {
      keep_Running.clear();
    }
    bool keepRunning() {
      return keep_Running.test_and_set();
    }
    virtual void process() = 0;
};

ComputationThread.h

ComputationThread.h

class ComputationThread : public WorkerThread {
  public:
    virtual void process() override {
      /**
       *  Perform computations with ~400MB data
       *  check every 16B, whether keepRunning still true
       */
      bool keep_running = true;
      while(keep_running) {
        /**
         * Process 4B
         */
        keep_running = keepRunning();
      }
    }
};

如果我使用某种标志来跟踪线程的运行状态,我必须使该标志成为线程安全的,不是吗?我尝试了std::atomic_flag,因为它应该是无锁的并且具有原子操作,但这会导致性能急剧下降.我的问题是,std::atomic_flag会导致性能下降还是仅仅是因为我执行检查频率太高?有谁知道更好的方法?

If I use some kind of flag, to track the running state of a thread, i have to make this flag threadsafe, don't I? I tried a std::atomic_flag because it should be lock-free and has atomic operations, but this results in a dramatically drop of performance. My question is, does the std::atomic_flag causes the performance drop or is this just because I perform the check way too often? Does anyone knows a better way?

在您问之前,我必须使用pthread而不是std::thread来将线程分配给线程创建过程中的指定核心(使用pthread_attrib_t).

Before you ask, I HAVE to use pthread instead of std::thread to assign a thread to a specified core within the thread creation (using pthread_attrib_t).

推荐答案

请勿使用std::atomic_flag.

它是低级atomic原语,因此具有非常有限的界面.
它的主要局限性是只能通过名为test_and_set()
的单个atomic调用中将其设置为true来测试其值. 这是一个读-修改-写操作(RMW),它在所有内核之间执行昂贵的同步. 由于您在每次循环迭代时都调用此函数,因此它的运行速度会大大降低.

It is meant as a low level atomic primitive and therefore has a very limited interface.
Its main limitation is that you can only test its value by setting it to true in a single atomic call named test_and_set()
This is a Read-Modify-Write operation (RMW) which performs expensive synchronization between all cores. Since you are calling this on every loop iteration, it slows down significantly.

使用常规的atomic<bool>并在完成后进行设置. 这样,您只需在循环内部读取它,这是一个atomic负载,可以转换为常规的mov操作. 设置特定的内存顺序将不会对性能产生影响(至少在X86上不会如此).

Use a regular atomic<bool> and set it once you are finished. This way, inside the loop you only have to read it, which is an atomic load and that translates to a regular mov operation. Setting a specific memory order will have no impact on performance (at least on X86).

这篇关于非阻塞pthread停止-或为什么std :: atomic_flag减慢我的代码的速度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆