首页 > 编程语言 >C++多核多线程同步实现

C++多核多线程同步实现

时间:2023-04-08 21:34:52浏览次数:32  
标签:同步 阻塞 dsp wait 线程 C++ 多核 多线程 cva

使用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

相关文章

  • C++,OpenCV图像像素运算(6)
    参与算术运算图像的数据类型、通道数目、大小必须相同算术运算加法:addvoidadd(InputArraysrc1,InputArraysrc2,OutputArraydst,InputArraymask=noArray(),intdtype=-1);/******************************************************************** src1: 输入图1* ......
  • C++primer第五章
    5.1 简单语句表达式语句的作用是执行表达式并丢弃掉求值结果。最简单h的语句是空语句,空语句中只有一个单独的分号。复合语句是指用花括号括起来的语句和声明序列,复合语句也被称为块。一个块就是一个作用域。5.2 语句作用域定义在控制结构内的变量作......
  • C++ 并发编程实战 第二章 线程管控
    第二章线程管控std::thread简介构造和析构函数///默认构造///创建一个线程,什么也不做thread()noexcept;///带参构造///创建一个线程,以A为参数执行F函数template<classFn,class...Args>explicitthread(Fn&&F,Args&&...A);///拷贝构造(不可用)thread......
  • C++primer第四章表达式
    4.1 基础4.1.1 基本概念当一个对象作为右值时,用的是对象的值。当一个对象作为左值时,用的是对象的身份(在内存中的位置)。如果表达式的求值结果是左值,decltype作用于该表达式得到一个引用类型。4.1.2 优先级与结合律括号优先级比较高。在第四章结尾处附上了......
  • 2023年蓝桥杯软件类省赛 C/C++ B组 解析
    还有一题忘了题意是什么了,等拿到题面了再更中间的题目顺序也忘了,填空题的数据也暂时还没有,暂时只有简单的思路,包括后面大题数据范围和是否多组都有点记不清A将题面序列处理成数组放代码里直接枚举八个位置的\(O(n^8)\)复杂度对于\(n=100\)的范围显然本地跑也跑不出来但由......
  • CMU_15_445_project_0_C++_Primer
    CMU15_445project_0C++Primertask1Copy-On-WriteTrieGetGet比较简单,遍历字符串和trie,找得到就返回值,找不到就返回nullptr.Put每个树有一个没有value的根节点,节点的类型分为TrieNode类和TrieNodeWithValue类,TrieNode是基类不存value,TrieNodeWithValue类继......
  • C++笔记(一)
    C++笔记(一)反复考量之后,还是决定将C++作为我的第二语言以及以后的主力开发语言。目录C++笔记(一)语法基础基本数据类型变量、常量作用域基本运算补码字节序基本结构顺序结构分支结构循环结构指针内存空间动态分配内存二级指针空指针野指针函数指针常见容器类型数组语法基础基本数......
  • C++竞赛常用函数库stl快捷查询手册(vector,map,set,queue,string等)
    1.控制输出流<iomanip>;cout<<setprecision(<span="">int);保留int位有效数字cout<<setprecision(<span="">int)<<fixed;保留int位有效小数为不足4位数的数填充0(如1填充变成0001),cout<<setfill('0')<<setw(4)(一次性效果)......
  • 回调函数 C++
    回调函数(CallbackFunction)是一种常见的编程模式,它是一段可以被传递给其他函数的代码,可以在特定的条件满足时被调用执行。回调函数通常作为参数传递给其他函数,以便在某些事件发生时执行。在C++中,回调函数通常是一个指向函数的指针,它可以作为参数传递给其他函数,这些函数可以在需要......
  • C/C++模拟ATM机存取款管理系统[2023-04-07]
    C/C++模拟ATM机存取款管理系统[2023-04-07]2、模拟ATM机存取款管理系统模拟银行的自动取款机使用过程中的界面和用户交互过程。实现查询银行卡余额、取款修改密码、退出系统等功能。(一)功能要求及说明:(1)将银行账户的卡号,户名,密码和账户余额从外部文件(银行账户.txt)中读入......