非阻塞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).