
文章插图
系统编程所谓系统编程,顾名思义,指的是有关操作系统的代码编写,如 Windows、Unix 系统编程 。和我们常见的应用编程有所不同,系统编程更接近硬件,且它使用的函数库和库函数调用方法也有所不同,那么,在面对更加复杂的系统编程时 , 作为开发者,又有哪些较好的优化措施呢?
作者 | Paul Cavallaro
译者 | 苏本如,责编 | 屠敏
出品 | CSDN(ID:CSDNnews)
以下为译文:
本篇文章中,将会概述一些常用的优化技术和“系统编程”的一些妙招 。不管今天的“系统编程”意味着什么,我们将介绍一些方法,以便你的代码运行更快、更加高效,并能让你从你得到的任何知识中收获更多的好处 。
这篇文章里讨论的所有示例可以在GitHub的这个地方获?。簆aulcavallaro/systems-programming 。
缓存线和伪共享
在现代对称多处理(SMP)系统上 , “伪共享”(False sharing)是一个非常容易理解的多线程代码优化的问题 。对于这个问题的讨论已经相当广泛了 。一个基本的思想是机器上的物理内存不是无限粒度的,也就是说,你不能仅仅读取一个字节 。相反,当你想要读取一个字节的内存时,处理器不仅会读入并缓存这个字节,而且会读入并缓存该字节周围的数据,因为它假设这些数据也可能被使用 。这个被读取和缓存的数据单元被称为“缓存线”,本质上它是可以访问的最小内存块 。
截至2019年,缓存线的大小都是2 的乘方,通常介于32到256个字节之间,其中最常见的大小是64个字节 。
现在,为了支持一台机器上的多个处理器以一致的方式从同一块内存中读和写,这台机器上必须只有一个处理器可以独占地访问给定的缓存线 。
“伪共享”是指意外地将两个不相关的数据块放在同一缓存行中 。当有两个处理器分别更新这两个不同的数据块中的数据时 , 比如多个计数器的值 , 就会产生互相干扰 , 因为每个处理器都试图以独占的方式访问包含这两个数据块的缓存线 。
对“伪共享”这个名称的解释是 , 尽管这两个计数器从理论上来讲不应该互相影响,但它们没有任何好的理由地“错误地共享”了一个缓存线 。
一种解决方案是将强行将数据写入到分开的缓存行上,在C/C++语言中,这可以通过强制结构体/类(struct/class)成员的对齐来实现 。在这个示例examples/cache-lines.cc中,我们使用abseil(注:谷歌内部使用多年的 C++ 代码库 , 现已开源)宏ABSL_CACHELINE_ALIGNED来实现这一点 。
为了证明实际效果,我们针对两个不同的结构体NormalCounters和CacheLineAwareCounters 中的std::atomic<int64> 类型的计数器做了基准测试 。
// NormalCounters is straight forward naive implementation of a struct of
// counters.
// Note: We also use ABSL_CACHELINE_ALIGNED on the NormalCounters struct, but
// not its members, so that the entire struct will be aligned to a cache line.
// Otherwise the struct might be placed towards the end of a cache line,
// accidentally straddling two cache lines, thereby improving its performance.
struct ABSL_CACHELINE_ALIGNED NormalCounters {
std::atomic<int64> success{0};
std::atomic<int64> failure{0};
std::atomic<int64> okay{0};
std::atomic<int64> meh{0};
};
// CacheLineAwareCounters forces each counter onto a separate cache line to
相关经验推荐
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 分公司需要营业执照吗
- 葡萄苗6月份能栽活吗视频 葡萄苗6月份能栽活吗
- 兔子要养多久才会生
- 上肉桂是什么东西
- 自制万能花肥营养液 自制万能花肥
- 卡西欧小方块怎么调表带
- 浙江新昌房价 浙江新昌
- 凡尔赛是什么意思
- 金诺三髓粉
- 春天开什么花的名字和图片 春天开什么花的名字
