《多核与GPU编程:工具、方法及实践》----3.4 信号量

简介: 信号量是一种软件抽象机制,由荷兰计算机科学家Edsger Dijkstra提出,它支持两种原子操作: P或加锁 V或解锁 不同的信号量实现使用不同的P和V的命名方法(例如Qt中使用lock-unlock以及acquire-release),但是语义与二元信号量或者计数信号量的实现是一致。

本节书摘来自华章出版社《多核与GPU编程:工具、方法及实践》一书中的第3章,第3.4节, 作 者 Multicore and GPU Programming: An Integrated Approach[阿联酋]杰拉西莫斯·巴拉斯(Gerassimos Barlas) 著,张云泉 贾海鹏 李士刚 袁良 等译, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.4 信号量

信号量是一种软件抽象机制,由荷兰计算机科学家Edsger Dijkstra提出,它支持两种原子操作:

P或加锁

V或解锁

不同的信号量实现使用不同的P和V的命名方法(例如Qt中使用lock-unlock以及acquire-release),但是语义与二元信号量或者计数信号量的实现是一致。

二元信号量或者互斥信号量(MUTua EXclusion,mutex)拥有一个表明目前是否加锁的状态。如果某个线程调用P或者V时将会进行如下操作:

P:如果信号量未锁定,则它将锁定并立即返回,调用线程可以继续执行。如果信号量锁定,则线程等待并置于一个等待线程队列Q中。

V:如果线程队列为空,则信号量设置为未锁定。否则,从等待线程队列Q中弹出一个线程T使其继续运行,这也是线程T从对信号量调用P函数中返回的时间点。以此类推可以判断何时信号量才会被重新设置为未加锁状态。

如果信号量的等待队列是一个先入先出队列,则称为强信号量。否则,称为弱信号量。此时,在等待线程间没有优先权机制,因此可能会导致某个线程长期处于加锁状态(这种现象称为饿死,将会在本节后面进行讨论)。

计数信号量(也称为一般信号量)有一个计数器状态C,表明有某种资源的可用数量(例如消息、文件句柄、缓冲区等)。当一个线程对一个计数信号量调用P和V时:

P:C减1:如果结果为负数,则线程被阻塞并被置于一个等待线程队列Q中。

V:C加1。如果结果为0或者负数,则从等待线程队列Q中弹出一个线程T使其继续运行。

虽然P和V这两个记号对于伪码的表达十分方便,但是在本节后面将利用Qt实现类及其方法,如表3-1所示。在Qt的信号量机制之外,还有一个使用方法,也被其他线程库使用,即tryAcquire/tryLock方法。它们允许主调线程非阻塞地尝试改变信号量状态。改变成功时返回TRUE,否则返回FALSE。


83e095b8155fc0a78af85dc6c7505b776e3da588

图3-8所示的示例展示了被三个线程共享的计数信号量状态的改变。

学习了Qt类,可以通过互斥机制解决代码清单3-6中所示程序的竞争条件问题。互斥量必须在所有参与线程间共享,因此它必须满足:


48465180f24cc600d87608eccfbc5933fd3b98c3

定义为全局变量。

作为一个构造函数参数传给所有线程。

后一种方式更好,其代码如代码清单3-7所示。这里利用的加锁-解锁对操作产生了一个关键区,即所有的线程是互斥执行的,某个时刻只能由一个线程位于关键区之内。关键区允许安全地访问共享资源,并且避免导致写入时进入不一致状态,或者读取错误数据的风险。理论上,应该限制关键区的大小或者停留时间,否则会降低引入多线程执行而带来的并发性效果。


308f9f528f6cfcf71f084b34ead8c1e447224bb6


3db04090dd53cde8180a3feddcbc926122c66f15

因为互斥可以作为锁来使用,所以其默认值是可以进入的。对于一般信号量而言,除非在构建时显式指定,否则其初始值是0。

上一个例子中引入的信号量较为简单和直接,但是信号量导致的挑战也是不能低估的。信号量是一种控制并发性的细粒度机制,提供了高性能并发的潜力,也提高了使用的难度。不仅竞争条件难以检测,而且解决这一问题的互斥量可能导致死锁或者饿死。

死锁是一种包含多个(两个或多个)线程的现象,线程无限期等待访问资源同时又拥有并且不放弃其他资源。图3-9展示了一个资源分配图的示例用以说明这种情况。


4b519cf2839a2dbe615fb230f5f61290435a105c

另一方面,饿死会影响单独的线程。当线程或者进程被挂起并且永远禁止执行时的情况称为饿死,即使可以继续执行也是如此。典型的饿死发生在强制线程优先级并且缺少公平调度或者访问资源时。

一个易犯的典型错误示例是:

获取(加锁)一个资源并且忘记对其

释放

释放一个从未获得的资源

在未加锁时使用一个资源,甚至只读操作也获取一个锁

但是,并没有学习如何适当使用信号量的有效方法。首先介绍信号量的几种不同用处,以及与每种用处相关联的软件模式。然后介绍应用一些软件设计中广泛涉及的经典问题。

一个信号量有三种不同的使用方法:

1.作为锁来使用。合适的信号量类型是二元信号量。

2.作为资源计数器使用。合适的信号量类型是一般信号量。

3.作为信号机制。合适的信号量类型是二元或者一般信号量,具体情况依赖具体应用。

下面将会证明,信号量可以同时扮演上述多个角色。

对于每种情况,存在如何对其进行配置的模式。图3-2展示了两个线程的模式。

表3-2可以作为一个引导,通过学习大量经典问题,来理解如何恰当地使用信号量。


2296fed742fac6a8d17dc23564d8621c46249f88
相关实践学习
基于阿里云DeepGPU实例,用AI画唯美国风少女
本实验基于阿里云DeepGPU实例,使用aiacctorch加速stable-diffusion-webui,用AI画唯美国风少女,可提升性能至高至原性能的2.6倍。
相关文章
|
3月前
|
人工智能 弹性计算 PyTorch
【Hello AI】神行工具包(DeepGPU)-GPU计算服务增强工具集合
神行工具包(DeepGPU)是阿里云专门为GPU云服务器搭配的GPU计算服务增强工具集合,旨在帮助开发者在GPU云服务器上更快速地构建企业级服务能力
129537 3
|
Unix 异构计算 Windows
带你读《基于CUDA的GPU并行程序开发指南》之一:CPU并行编程概述
本书旨在帮助读者了解与基于CUDA的并行编程技术有关的基本概念,并掌握实用c语言进行GPU高性能编程的相关技巧。本书第一部分通过CPU多线程编程解释了并行计算,使得没有太多并行计算基础的读者也能毫无阻碍地进入CUDA天地;第二部分重点介绍了基于CUDA的GPU大规模并行程序的开发与实现,并通过大量的性能分析帮助读者理解如何开发一个好的GPU并行程序以及GPU架构对程序性能的影响;本书的第三部分介绍了一些常用的CUDA库。
|
2月前
|
并行计算 API 开发工具
【GPU】GPU 硬件与 CUDA 程序开发工具
【GPU】GPU 硬件与 CUDA 程序开发工具
42 0
|
2月前
|
机器学习/深度学习 并行计算 流计算
【GPU】GPU CUDA 编程的基本原理是什么?
【GPU】GPU CUDA 编程的基本原理是什么?
48 0
|
4月前
|
存储 人工智能 缓存
探索AIGC未来:CPU源码优化、多GPU编程与中国算力瓶颈与发展
近年来,AIGC的技术取得了长足的进步,其中最为重要的技术之一是基于源代码的CPU调优,可以有效地提高人工智能模型的训练速度和效率,从而加快了人工智能的应用进程。同时,多GPU编程技术也在不断发展,大大提高人工智能模型的计算能力,更好地满足实际应用的需求。 本文将分析AIGC的最新进展,深入探讨以上话题,以及中国算力产业的瓶颈和趋势。
|
缓存 openCL 算法
关于实现Halcon算法加速的基础知识(2)(多核并行/GPU)
关于实现Halcon算法加速的基础知识(多核并行/GPU)
2560 0
关于实现Halcon算法加速的基础知识(2)(多核并行/GPU)
|
10月前
|
机器学习/深度学习 程序员 异构计算
【深度学习工具】Python代码查看GPU资源使用情况
在训练神经网络模型时候,有时候我们想查看GPU资源的使用情况,如果使用Ctrl+Shift+Esc不太符合我们程序员的风格😅,如果可以使用代码查看GPU使用情况就比较Nice。话不多说,直接上代码。
557 0
|
Android开发 开发者 异构计算
【Android 性能优化】布局渲染优化 ( GPU 过度绘制优化总结 | CPU 渲染过程 | Layout Inspector 工具 | View Tree 分析 | 布局组件层级分析 )(二)
【Android 性能优化】布局渲染优化 ( GPU 过度绘制优化总结 | CPU 渲染过程 | Layout Inspector 工具 | View Tree 分析 | 布局组件层级分析 )(二)
226 0
【Android 性能优化】布局渲染优化 ( GPU 过度绘制优化总结 | CPU 渲染过程 | Layout Inspector 工具 | View Tree 分析 | 布局组件层级分析 )(二)
|
Android开发 开发者 异构计算
【Android 性能优化】布局渲染优化 ( GPU 过度绘制优化总结 | CPU 渲染过程 | Layout Inspector 工具 | View Tree 分析 | 布局组件层级分析 )(一)
【Android 性能优化】布局渲染优化 ( GPU 过度绘制优化总结 | CPU 渲染过程 | Layout Inspector 工具 | View Tree 分析 | 布局组件层级分析 )(一)
368 0
【Android 性能优化】布局渲染优化 ( GPU 过度绘制优化总结 | CPU 渲染过程 | Layout Inspector 工具 | View Tree 分析 | 布局组件层级分析 )(一)
|
算法 安全 程序员
关于实现Halcon算法加速的基础知识(1)(多核并行/GPU)
关于实现Halcon算法加速的基础知识(多核并行/GPU)
1060 0
关于实现Halcon算法加速的基础知识(1)(多核并行/GPU)