微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 硬件工程师文库 > 谢宝友教你学Linux:深入理解Linux RCU之从硬件说起

谢宝友教你学Linux:深入理解Linux RCU之从硬件说起

时间:08-04 来源:电子发烧友网工程师 点击:


一、来自于霍金的难题

据说斯蒂芬·霍金曾经声称半导体制造商面临两个基本问题:

(1)有限的光速

(2)物质的原子本质

第一个难题,决定了在一个CPU周期内,电信号无法在整个系统所有CPU中广播。换句话说,某个CPU指令对一个内存地址的写操作,不会在这条指令执行完毕后,马上被其他CPU识别到操作结果。例如:CPU0对全局变量foo执行foo = 1,当CPU 0执行完相应的汇编代码后,其他CPU核仍然看到foo赋值前的值。刚接触操作系统的读者,需要注意这一点。

第二个难题,导致我们至少需要一个原子来存储二进制位。没有办法在一个原子中存储一个字、一段内存、一个完整的寄存器内容......最终的结果是,硬件工程师没有办法缩小芯片流片面积。当CPU核心增加时,核间通信的负担会变得更加沉重。

当然,作为理论物理学家,霍金的这两个问题都是理论性的。半导体制造商很有可能已经逼近这两个限制。虽然如此,还是有一些研发报告关注于如何规避这两个基本限制。

其中一个绕开物质原子本质的办法是一种称为"high-K绝缘体"的材料,这种材料允许较大的器件模拟超小型器件的电气属性。这种材料存在一些重大的生产困难,但是总算能将研究的前沿再推进一步。另一个比较奇异的解决方法是在单个电子上存储多个比特位,这是建立在单个电子可以同时存在于多个能级的现象之上。不过这种方法还有待观察,才能确定能否在产品级的半导体设备中稳定工作。

还有一种称为"量子点"的解决方法,使得可以制造体积小得多的半导体设备,不过该方法还处于研究阶段。

第一个限制不容易被绕过,虽然量子技术、甚至弦论,理论上允许通信速度超过光速。但是这仅仅是理论研究,实际工程中还未应用。

二、原子操作有多慢?

这里的原子操作,是特指Linux内核中,类似于atomic_long_add_return这样的API。简单的说,就是当某个原子操作完成时,确保所有CPU核已经识别到对原子变量的修改,并且在原子操作期间,其他CPU核不会同步对该变量进行修改。这必然要求相应的电信号在所有的CPU之间广播。如下图:

对于普通变量操作(非原子操作)来说,电信号则不必在所有CPU核之间传播并来回传递:

不能忘记一点:Linux操作系统可以运行在超过1024个CPU的大型系统中。在这些大型系统中,在所有CPU之间广播传递电信号,需要花费"很长"的时间。

但是,很长究竟是多长?

在上表中,一次"CAS cache miss"的CPU周期是266,够长了吧?而这个测试结果,是在比较新的、4核CPU的多核系统中进行的。在老一点的系统中,或者在更多CPU核心的系统中,这个时间更长。

三、变量可以拥有多个值

这不是天方夜谭。

假设CPU 0向全局变量foo写入一个值1,我们会很自然的认为:其他CPU会立即识别到foo的值为1。即使有所疑惑,我们可能也会退一步认为,在稍后某个时刻,其他"所有"CPU都会"同时"识别到foo的值为1。而不会出现一种奇怪的现象:在某个时刻,CPU 1识别到其值为1,而CPU 2识别到其值为0。不幸的是,是时候告别这种想法了。并行计算就是这么神奇和反直觉。如果不能理解这一点,就没办法真正理解RCU。

要明白这一点,考虑下面的代码片段。它被几个CPU并行的执行。第 1行设置共享变量的值为当前CPU的ID,第2行调用gettb()函数对几个值进行初始化,该函数读取硬件时间计数,这个计数值由SOC硬件给出,并且在所有CPU之间共享。当然,这个硬件计数值主要是在power架构上有效,笔者在powerpce500架构上经常使用它。第3-8行的循环,记录变量在当前CPU上保持的时间长度。

1 state.variable = mycpu;

2 lasttb = oldtb = firsttb = gettb();

3 while (state.variable == mycpu) {

4   lasttb = oldtb;

5   oldtb = gettb();

6   if (lasttb - firsttb >1000)

7     break;

8 }

在退出循环前,firsttb 将保存一个时间戳,这是赋值的时间。lasttb 也保存一个时间戳,它是对共享变量保持最后赋予的值时刻的采样值,如果在进入循环前,共享变量已经变化,那么就等于firsttb。

这个数据是在一个1.5GHz POWER5 8核系统上采集的。每一个核包含一对硬件线程。CPU 1、2、3和4记录值,而CPU 0 控制测试。时间戳计数器周期是5.32ns,这对于我们观察缓存状态来说是足够了。

上图的结果,展示出每个CPU识别到变量保持的时间。每一个水平条表示该CPU观察到变量的时间,左边的黑色区域表示相应的CPU第一次计数的时间

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top