使用Makefile C++11工程模拟dsp的多核同步逻辑,使用多线程模拟多核,多个线程通过C++11的条件变量实现同步。 当某一线程执行到同步函数syn_func时,判断是否其他线程执行到此处了,若有其他线程没有执行到此处,本线程就应阻塞。 当最后一个线程执行到同步函数时,通知所有线程解除阻塞,实现同步。 为了实现这个过程,首先需要一个条件变量,阻塞各线程。其次,需要一个全局变量,作为各线程运行到位的依据。所以一个简单的实现:
1 mutex dsp_lock; 2 condition_variable dsp_cva; //条件变量 3 vu32 dsp_cva_no=0; //多核同步的数量 4 5 void syn_func() //多核同步 6 { 7 unique_lock<mutex> lk(dsp_lock); 8 dsp_cva_no++; 9 if(dsp_cva_no>=NCORES) //若自己是最后一个 10 { 11 dsp_cva_no=0; 12 dsp_cva.notify_all(); 13 } 14 else dsp_cva.wait(lk); //若不是,就等,单独的wait可能造成虚假唤醒 15 }这个实现逻辑非常简单,但条件变量的wait函数可能造成虚假唤醒,导致失步。所以必须使用带条件的wait函数来实现。 条件变量的wait函数在带锁的条件下执行条件函数,确定是否需要等待,若需要等待,就解除互斥锁,并阻塞线程。 由于解除阻塞时多了一个 加锁-判断-解锁 的过程,先完成的线程会立刻执行同步点之后的程序,可能会修改同步变量,从而导致后执行的线程判断错误。 所以需要修改同步变量的机制,改为记录每个核的同步序号,每次同步时序号加1。为处理序号溢出问题,判断时,判断本线程序号是否等于其他线程的序号减1,从而得出其他线程是否已经进入下一个同步点的结论。
1 mutex dsp_lock; 2 condition_variable dsp_cva; //条件变量 3 vu32 dsp_cva_no[NCORES]={0}; //每一个核1个序号 4 5 void syn_func() //多核同步 6 { 7 unique_lock<mutex> lk(dsp_lock); 8 int cn=coreNum; 9 dsp_cva_no[cn]++; 10 dsp_cva.wait(lk,[cn]() 11 { 12 for(int i=0;i<NCORES;i++) 13 { 14 if(dsp_cva_no[cn]!=dsp_cva_no[i] && //若有不同步的 15 dsp_cva_no[cn]!=(dsp_cva_no[i]-1)) //或其它核已经进入下个了 16 { 17 return 0; //未同步,有的核没跟上 18 } 19 } 20 return 1; 21 }); 22 dsp_cva.notify_all(); 23 }程序中,调用同步函数直接就调用wait函数,通过条件函数判断是否需要阻塞。阻塞的标准是各线程步骤序号不同。最后一个同步的线程不经阻塞,直接调用notify_all,通知所有线程开始执行。即使第一个线程已经执行到下一个同步点,修改了同步变量,其他线程判断同步变量时,也能判断出自己是落后的,从而解除阻塞。 所有线程解除阻塞时,都会调用notify_all函数,但不会对同步造成影响,因为线程阻塞时会判断同步变量才解除阻塞。 标签:同步,阻塞,dsp,wait,线程,C++,多核,多线程,cva From: https://www.cnblogs.com/yangzifb/p/17299278.html