并发编程
早期 CPU 通过提高主频来提升 CPU 的性能,不过因为工艺问题以及摩尔定律的终结,目前更加倾向于多核心的发展,对于编程来说,更像一个小型的分布式系统,也导致多线程编程要难很多。
另外,为了弥补 CPU 与主存处理速度的差异,在两者之间增加了多级缓存,提升性能的同时,也带来很多编程上的问题,尤其对于 Lock-Free 的编程。
内存一致性模型(memory consistency model)就是用来描述多线程对共享存储器的访问行为,在不同的内存一致性模型里,多线程对共享存储器的访问行为有非常大的差别。这些差别会严重影响程序的执行逻辑,甚至会造成软件逻辑问题。在后面的介绍中,我们将分析不同的一致性模型里,多线程的内存访问乱序问题。
并发编程
并发编程涉及到很多的知识点,包括了从编译器、到 CPU 、内存与 Cache 的关系等等,都有可能会导致代码与实际执行不一致,原则是保证单线程下的一致。
- 基本介绍 这里介绍原子变量的基本操作。
- 内存顺序 通过原子变量的内存序,从而解决数据竞争问题。
- 硬件支持 所有的原子操作需要硬件平台的支持。
- 线程同步 如何通过传统的互斥锁、条件变量、信号量等处理高并发场景,以及 CPP 版本。
- 线程变量 允许各个不同线程保存各自变量。
- Memory Reordering 包括了编译器乱序、CPU 乱序等,及其实例。
- Lock Free 通过 Queue 介绍 Lock Free 编程方式,实际还有 Wait-Free 的实现。
向量编程
- 基本概念 Intel 中相关的基本概念。
- 编译优化 大部分的场景可以通过编译器直接进行优化,有效减少复杂场景的处理。
- 内置指令 也就是 Intrinsic 函数,相比汇编要更加简单,其命名也有规律可循。
- 动态转发 允许单个二进制包支持不同平台指令,从而可以简化版本分发。
- 基础示例 介绍一些简单的入门示例。
其它
- RCU 适用于读多写少的场景,对读取路径有很大优化,频繁写入反而会导致性能下降。
- Persistent Data Structure 这里并非持久化到存储中,而是指操作时保留多个版本,常用在函数、并发编程。
参考
- Preshing 原子操作不错的介绍网站,不过最近更新在 2021 年,不确定后续会不会断网。
- Johnny’s Software Lab 有很多不错的性能优化文章,例如 SIMD、分支、DataCache 等等底层优化。
- C++ Concurrency in Action 一篇很经典的并发编程介绍,可以从 PDF 下载。
- Is Parallel Programming Hard, And, If So, What Can You Do About It? 一篇不错的介绍文章,包括了免费的 PDF 。