【NV-02】CUDA 并行计算--线程和索引
Paxos算法并不长,写在纸上也仅有短短的四句话。它之所以看起来有些像是微言大义的天书,主要是我们并不清楚这几条简单规则背后的设计意图是什么,为什么它能起作用,不采用这些规则是不是就不行?分布式系统的底色是生的自由、死的随机的一片混沌,矛盾冲突无处不在,但是Paxos算法却偏偏在这一片混沌之上建立了统一一致的共识世界,这看起来宛如神迹。但是,凡人是很难理解神迹的,他无法站在神的高度俯瞰众生,只能凭借自己有限的生活经验去追索揣摩神的意图,最终必然会产生属于凡人的困惑。本文试图从异次元魔法学的角度对Paxos算法做一个解读,建立Paxos算法背后简明的魔法学图像,从而实现我们对这个算法的直观理解。
首先我们来看一下神所面临的问题,以及他可能的烦恼之处。
假设神需要让一队人马去集体完成同样的事情。他所遇到的第一个问题就是所有人都不靠谱。你向A分配任务,他可能因为神游物外压根没有听见,也可能反应迟钝、磨磨蹭蹭,最过分的是直接中途躺倒,拒绝工作。这个问题相对来说比较好解决,一个人不靠谱无所谓,只要一堆人中有几个靠谱的就行,先进可以带动后进。神只要每次抓住几个骨干,指导他们把事情做好,剩下的人再从骨干那里学习神谕即可。
真正棘手的问题是,总有很多事情在并行的发生。神刚给A分配好工作,正在给B讲解的时候,A的情况又发生了变化(比如接到了别的神的神谕)。神只能屁颠屁颠的跑回A处,给他分配新的神谕。这边A刚搞定,那边B又出新的幺蛾子了,神又忙不迭的拍马赶到。这么搞了几次之后,作为至高无上、全知全能、无远弗届的神,即使脾气再好,他也会忍不住发作的。
神是凌驾于一切有限客体之上的最完满的存在,所以他并不会真的遇到上述烦恼。因为,他只要轻轻说一声:定,施展一个九级魔法”时间静止“就可以让这个嘈杂的世界彻底安静下来,然后从容的去做任何他想做的事情。
按照我们这个位面的现代物理学的理解,所谓的时间只是对变化的一种度量。我们通过比较钟摆的周期运动和其他运动的关系来建立时间的概念。如果没有发现任何变化,实际上意味着感知到的时间保持不变。特别的,如果宇宙中所有原子的振荡齐齐的慢了一拍,身处其中的人类是无从发现的。
回顾一下Paxos算法的步骤,Proposer先通过promise步骤,从所有Acceptor处确定一个唯一的ProposalID,然后当发生任何需要识别的事件时,例如接到了新的消息,ProposalID都会自动增加,因此ProposalID实际上就是某种时间的标记。当Acceptor接收到accept消息时,如果发现ProposalID与此前promise时相比没有变化,则可以判定在此过程中时间保持静止,没有任何需要关注的事件发生。
每一个Acceptor都记录了一个只增不减的ProposalID,相当于建立了本地的时间箭头。而整个系统通过ProposalID对齐到同一时间点,相当于是将多个局部的时间箭头对齐后,捆绑为一个粗粒化的、整体性的时间箭头(对齐的前提条件是同样的时间点上发生的事件完全相同,例如设置同样的值)。时间的流逝类似于波阵面扫过整个系统。
所以,从神的视角来看,Paxos算法不过是通过时间静止魔法,强行将多条时间线对齐为唯一的一条主时间线的雕虫小技而已。
这种”停止-对齐“的技术是我们在分布式系统中获得共识的一种基本策略。例如,在kafka消息队列中,同一个消费者分组中的多个消费者是独立行事的,但同时它们必须就如何分配工作达成共识。因此,当消费者分组中的成员增减或者topic结构发生变化时,会触发所谓的再平衡(Rebalance)过程。再平衡过程中,Coordinator首先要求所有worker停止当前的工作,集体切换到下一个世代(epoch),然后再下发新的分配方案。一个分配方案仅在一个世代中有效。
我们在数据库中常用的乐观锁也是同样的处理策略。刚进入处理程序的时候去读取MainRecord的版本号,然后再修改MainRecord以及相关联的SubRecord,最后在一个事务中批量提交修改,同时尝试更改主记录的版本号。
如果能够更新成功,说明在整个处理过程中时间静止,没有其他人执行相冲突的动作。
施展九级魔法是相当消耗魔力的行为。一个具有社会主义核心价值观、勤俭节约的神绝对不会无端的浪费魔力。所以一旦时间静止下来,为了维系分处多地的节点的行为一致,神的最佳选择是施展一个八级魔法”大傀儡术“,将一个节点上的行为复刻到其他所有节点上。
这种复刻源自于神的力量,因此一旦leader发动新的动作,它将穿越千山万水,无视物理阻隔直接降临于远端的follower身上,follower没有反驳的权利,只有执行的自由。不过,俗话说的好,上面动动嘴,下面跑断腿。在我们这样一个低魔世界中,实现大傀儡术并不是一件很轻松的事情,一般通过在发送端和接收端各自增加一个日志文件来实现。
发送端把动作决定写入日志,从而使它成为不可变的神谕。发送组件扫描日志系统,确保将其逐条传达到远端。如果连接不上接收端,或者发送出错,或者发送后没有接收到期待的响应信息,发送组件不能抱怨,不能放弃,唯有努力工作,不断重试,直到接收到成功响应为止,这一过程可以保证至少成功发送一次(At Least Once)。接收端必须无条件接收所有消息,不能拒收,不得篡改。因为有可能多次接收到同一个消息,它必须通过本地日志进行幂等检查,过滤掉所有重复消息,从而实现最多成功处理一次(At Most Once)。如果消息需要通过一个流式处理系统(Stream)进行接力处理,为避免每次从源头开始不断重播,需要中间节点能够通过快照机制把已经完成的处理结果记录下来。
毫无疑问,MultiPaxos和Raft算法都是以上复刻策略的一种具体实现。一旦选主成功,代表任期的Term编号就可以被多次复用,通过同一个Term编号可以发出多条执行指令,只要这些指令通过log index能够区分即可。
如果仔细分析一下,我们会发现,从网络上接收到的消息可以分成两类:一类是请求(Request),接收方可以自由选择相应的处理方式,处理结果也是不确定的,可以成功返回也可以抛出异常。另一类是单向的通知(Notice),它对应的处理方式是固定的,接收方不能有反驳的意见。i
一个有趣的例子是两阶段提交。在Prepare阶段,Participant接收到的是请求消息,因此它可以根据自己的独立意志选择提交或者回滚。一旦Participant将自己可能的选择返回给Coordinator,它就向Coordinator让渡了自身的自主权,许诺今后只接收通知消息,将行为与Coordinator保持一致。当Coordinator决定提交时,Participant绝不会选择回滚。同样的,Participant如果回滚,我们知道Coordinator的选择也只能是回滚。它们两者的选择不再是独立的做出,而是纠缠在了一起。
如果我们单独看待各个Participant和Coordinator,它们各自都可能随机的处于提交和回滚两种状态。但是如果我们把它们作为整体来看待,我们会发现并不是所有状态都是可能的,只有|提交,提交>和|回滚,回滚>是整个状态空间中允许的状态,也就是说2PC运行的过程中,整个系统实际处在|提交,提交>和|回滚,回滚>所构成的量子纠缠态中!
基于上面的考虑,在我们这个位面中,量子纠缠不失为实现傀儡术的一种可行机制。
作为一介凡人,我们并没有魔力去驱动魔法。但是我们都看过魔术,也都经历过所谓”见证奇迹的时刻“。奇迹的诞生源于魔术师引导我们只去观察显露出来的事实,under the hood的秘密则是不足为外人道也。魔法作为魔术的加强版,本质上的原理也是类似的:只要确保所有不符合魔法学原理的事实都从我们的认知中删除就好了!
Paxos算法运行起来之后,我们试图让时间静止下来,但是恼人的干扰信息总是不停出现。Acceptor有可能会接收到来自过去的消息(ProposalID小于当前值),Paxos算法的解决方案就是假装没看见,直接扔掉!另一方面,Acceptor也有可能会接收到来自未来的消息,最简单的解决方案仍然是直接扔。但是这样的话会产生类似分布式锁的情况,导致容错性不够:在本次时间静止的周期里,有可能Proposer已经挂掉,没法继续完成向Acceptor设值的任务。所以面对当前和未来两个抉择,为稳妥起见,Acceptor只能放弃本次周期已经取得的成果,选择未来的可能性(魔法失败并不丢人,假装没看见,继续下一轮呗)。当然,如果Acceptor已经通过Learner机制知道当前值已经被选定,那就没有必要继续运行下一轮Paxos算法了,可以直接拒掉来自未来的请求。类似的,在Raft协议中,为了避免集群不断重新选举导致振荡,在一定时间内只要通过心跳信息确定Leader仍然存在,则来自未来的RequestVote消息也会被无情的抛弃。
在需要Leader选举的算法中,一个经典的问题是如何避免脑裂?如果新生代的Leader已经得到了人民的拥护,而老一代的Leader却不肯退位,总在那里不停的搅局怎么办?一个一般性的解决方案就是:直接把旧Leader定义为zombie, 彻底忽略来自上一个世代的所有信息(比如拒绝所有epoch较小的请求)。实际上,我们并没有限制旧Leader的行为,在自己的小世界中,它完全可以自以为是的为所欲为,只不过它的行为最终无法上升为集体意志,无法对主世界产生影响而已。新的Leader一继位,需要未读先写,先在主世界中打上自己的epoch标记(类似于更改全局共享变量),这样老的Leader在提交计算结果的时候通过乐观锁发现自己已经失势,最终只能无奈放弃自己的处理结果。
在我们这个位面的物理学中,随着量子力学的发展,观察或者说测量已经具有了非常独特的理论意义。按照量子场论所描绘的视图,在我们看不见的虚时间中,无数狂野的事物在相互竞争、湮灭,最终反映到现实世界中的只是某种综合运算后的结果而已。透过诡异的量子隧道效应,实际上我们也可以窥见这背后的惊涛骇浪。
掩耳盗铃并不是一个荒唐的笑话,而是在我们这个世界中可以真实运行的法则。如果能有效的制造遮蔽一切的信息茧房,它是可以操纵我们所认知的世界真相的。所以,懂王,一个号称无限接近于神的男人,一直在疯狂的暗示:不检测,新冠肺炎就不存在!作为一个泄漏天机的盗火者,懂王,他真的很懂。
神说,众生平等。用数学的语言来解释,就是每个人都没有特殊性,他们是对称的(Symmetric)!一个社会不能只有一种声音,每个人都可以有自己的意见,每一种意见都值得得到同样的尊重,那凭什么最后有一个人的声音被选择出来,盖过所有其他人的声音,最终成为所有人的共识?本质上,这是一个打破平等的过程,数学上称之为对称破缺(Symmetry Broken)。
最基本的一种对称破缺技术是多数派投票。因为一个集合里不可能同时存在两个多数派,所以只要在任意一个时刻(由ProposalID来确定),我们知道多数Acceptor都接受了某个值,我们就说这个值成为了被选定的值(chosen value),共识就达成了。
当共识出现的时候,参与者中有谁知道已经达成了共识吗?一个有趣的事实是,当共识达成的那一刹那,系统中所有的参与者,包括Acceptor和Proposer,没有任何人知道共识已经达成!只不过,随着时间的推移,算法的运行会把共识已经达成这一事实逐步的揭示出来。
考虑有5个Acceptor,多个Proposer的情况。在ProposalID=t1的时候,提案P1被A1和A2接受,但是没有达到多数派,因此在这一轮处理中值并没有被确定下来。ProposalID=t2的提案P2同样没有达到多数派。ProposalID=t3的提案P3被多数派A2、A3、A4接受,从而达成共识。
首先,我们注意到当共识没有达成之前,Acceptor是有可能改变自己接受的值的,例如A3先接受了P2,后面又接受了P3。因为Proposer随时有可能失联,所以Acceptor只能选择接受新的值。这导致当A3接受P3的时候,它不可能知道共识已经达成,P3就是最终选定的值。同样的道理,A2和A4也只知道自己局部的情况,无从判断系统整体是否已经达成共识。而在Proposer一端,在接收到多数派Acceptor的成功响应之前,它也不知道自己提交的P3能否被多数Acceptor接受,成为最终的共识。所以说共识是属于整体的,单个参与者对于共识是否达成需要有一个理解的过程。
在上一节的例子中,当ProposalID=t3达成共识之后,有没有可能在t4时刻我们达成一个新的共识P4?这样的话,t3的共识是P3,t4的共识是P4,而t1和t2时刻没有达成共识。对神来说,不同的时刻选定不同的值是完全OK的,No Problem,因为神是全知全能的。但是对于鲁钝的凡人而言,如果允许不同的时刻有不同的共识,他会出现认知障碍。
假如允许共识被推翻,一个只有有限认知能力的凡人,他怎么知道哪个值才是要用的值呢?很多时刻根本没有达成共识(例如t1和t2),他要从t1到tn遍历所有的时刻来获知所有共识的值吗?
现在,考虑上图中的情况。假设A3在处理P3的时候直接宕机了。从外部看来,存在两种情况:
A3已经接受P3,所以达成了共识A3还没有接受P3, 所以尚未达成共识除了A3自己之外,没有任何人知道它的处理情况。但是,A3已经挂掉了,它不能回答任何问题!所以,如果不同的时刻可能有不同的共识,那么我们有可能会陷入一个尴尬的境地,那就是历史结果完全处于一种量子不确定状态,无法简单的回答是或者否。
对于凡人而言,最理想的选择是系统具有某种单调性:它只会向着一个方向不断迈进,而且一旦到达目标状态,就永远禁锢于该状态中。这样的话,任何时候我们想从系统中提取信息,都可以直接将系统向前推进一步。如果系统已经达成共识,则继续前进一步得到的仍然是共识的值,如果没有达成共识,则我们将实际选定一个值,从而摆脱不确定的状态。例如,在上面的例子中,我们继续运行一步Paxos算法,无论t3时A3做出何种选择,我们一定会在t4得到P3的结果,从而在t4之后消除了系统中的不确定性。在郁白的文章中,这也称为最大提交原则。
注意,我们有可能因为多运行一趟Paxos算法,从而把系统从原本不确定的状态带到了确定状态。这就类似于量子系统,你观察一下它,它的状态就塌缩为某个本征态。如果此前它已经处于本征态,则观察行为不改变系统的状态。
共识是在主世界的主时间线上存在的知识。根据现代魔法学的研究,时间线的两个不同点上的知识是完全独立的!如果我们希望给这两个点上的知识建立关系,那必须引入某种”联络“机制,使得信息可以从一个时间点传递到另一个时间点。
首先我们知道所有主时间线上的事实肯定能按照发生的”时间点“排序,而共识是在主时间线的某个时间点上发生的写入。那么保持共识一致的最简单的方案就是,未写先读,写入之前先偷看一眼前面的情况。
在t4写入的时候如果能够偷偷看一眼t3的结果,直接使用t3的结果作为t4写入的值不就可以确保一致了吗?
在九级魔法的加持下,只需神念一动,即可在主时间线的任意一点完成读-处理-写这样一个复合的原子事件。主时间线上的事件可以分解对应到下级小世界中的事件。西游记中曾经记载:天上一日,人间一年。所以主世界的一点就映射为小世界中的一个区间了(小世界中如果有一个本地时钟,它会发现起始-处理-结束是一个较长的过程,而不是一个时间静止的点)。这种映射是保持了事件的原子性和相对位置关系的。例如,在上图中,A5的t4和t3都是不可分的,它们不会交叉。如果t3和t4交叉了,说明时间静止的区间内发生了意料之外的事情,这与时间静止的假定相矛盾。t4一定处于t3的后面,而且不会与t3相交,因此它一定可以看到t3的结果。
Paxos算法在第一阶段会收集多数派Acceptor上已经接受的值。
如果共识已经达成,则第一阶段一定会返回这个共识的值,而且它一定是ProposalID最大的那个值。证明:如果t3时刻达成了共识,则紧随其后的t4一定看到了t3的结果,按照规则,它的值一定是共识的值。所以如果ProposalID最大的值不是共识的值,则表示在它之前不可能已经达成共识。 如果共识尚未达成,则Proposer可以自由选择自己心仪的值,所以他主动成全别人,选择ProposalID最大的那个值也是完全允许的。 也许有些人会感到奇怪,Proposer提交别人的值,那他自己的值怎么办?请注意,Paxos算法的目的是实现共识,并不是为了满足个人的私欲,将自己的值变成共识。其实Proposer发现自己的值无法提交之后,他完全可以放弃后面的工作,并不影响算法的正确性。他主动帮助别人只是加速了系统的收敛过程。如果某个Proposer接收到了所有Acceptor的响应,他经过分析发现尚未达成共识,那么他完全可以选择不支持别人,坚持提交自己的值。互相帮助是人类的美德,这一次帮助别人推波助澜,下一次说不定别人也会帮助自己不是。
在凡人的眼中,这个世界充斥着令人心烦意乱的不确定性,每一步行为都产生三种可能的结果:1. 成功,2. 失败 3. 不知道什么结果。曾几何时,孤立的单机系统为我们提供了一种乌托邦式的幻象,世界是二分的,好与坏,成功与失败,光明与黑暗。但是真实的世界让人清醒,在由偶然所主宰的世界中,这种内在的不确定性造就了分布式系统的本质性的困难。
为了在一个偶然的、不确定的世界中奋力求生,我们唯有精诚合作,形成超越个体的集体意识。个体可以消亡,而集体通过新陈代谢实现永生。一个有趣的问题是,多数派(Majority)是否是形成集体意识的唯一选择?显然不是。精神的传承,只需要种子的存在。
来看一个Grid Quorum的例子,
对于上面个Acceptor所组成的一个Grid,我们可以规定只要写入任意一列所构成的Quorum即可认为共识达成。显然,任意两列都是不相交的。为了避免做出自相矛盾的选择,我们需要横向架设一个桥梁,规定Paxos第一阶段读取的时候必须至少读取一行。假设某个时刻共识已经诞生,则下一个共识必然先经过一个行读取再执行一个列写入。因为任意的行和任意的列都是相交的,行读取必然会读到共识的值,因此写入的新值必然是和此前的共识保持一致的。注意到这个例子中的行Quorum与相交的列Quorum都没有达到多数派,而且它们的总元素个数为3+6-1=8个,也没有构成多数派。所以,读取和写入时候的Quorum既不需要相同,也不需要占据多数,只要能够相交,足以传递信息即可。
要超越个体,只需要把个体升华为Quorum中的一员。一个个体可以属于多个Quorum。只要过去和未来所有的Quorum协调一致,不会做出相互冲突的选择,最终我们就可以形成统一的集体意志。
对于凡人而言,时间是一种神奇的先验存在。似乎我们所有的协调工作本质上都是在利用时间箭头所提供的方向指引。在我们这个位面,牛顿爵士第一个发现,时间切分了因果,时间的左边是因,右边是果,为此他写下了伟大不朽的牛二定律
F = m* a,因 = 线性系数 * 果 后来,爱因斯坦通过想象发射一个光子去探测周围的世界,不经意间揭示出一个惊天的秘密:时间线并不是唯一的!
如果时间线不唯一,我们该如何避免迷失方向?一个选择是,记住所有的时间线,这形成了所谓的向量时钟(Vector Clock)技术。而如果我们选择将所有的时间线对齐为唯一的一个,就成为了Paxos算法。
我们还有其他的选择吗?想象一下,如果可以彻底摆脱因果的枷锁,在时间线上自由的穿梭,无所谓过去,也无所谓未来,那是何等的拉风。因在左,果在右,为什么不能颠倒过来?本质上这是因为系统不满足交换律,当左右颠倒的时候得不到同样的结果。只有在一个高魔的世界中,无所谓左右,无所谓前后,在那里才可以施展真正的十级魔法:逆乱因果。CRDT数据结构了解一下?
人神之分,在于神域。神域之中,言出法随。制定规则,是神的起点,而谦卑的接纳规则、并狡诈的利用规则则是人之本质。
凡人中的一小撮人,名为程序员,自诩程序世界的伪神,总是试图僭越这一道鸿沟。但只有真正模拟过神的行为,人才能真正认识到自身的局限性和神的伟大。为什么发送了消息能接收到回应?因为所有的服务器都存放在地球上,它们之间距离有限。为什么可以通过本地时钟决定Lease租期?因为所有的服务器都存放在地球上,所处的引力场相近,本地时钟具有可比性。站在人的尺度上,我们是无法想象如何才能穿越大半个银河去实现共识的。
最后,让我们再次聆听一下神的意旨:
神说:要有时间
神说:时间静止
神说:大千世界
神说:亿万分身
神说:薪火相传
Lamport: Paxos!
* gitee: canonical-entropy/nop-entropy
* github: entropy-cloud/nop-entropy
1、千万不要为群众利益强出头!群众眼睛是瞎的!
2、适当冷漠,可以减少你90%的麻烦。
3、喋喋不休,是一个男人、女人掉价最快的行为。
4、别怂,你在有权人面前,该你说的时候,越怂越不得志。
5、和生人交往的最好方式,就是让ta先看到利益。
6、王志文有句台词,说点好话能搞定50%的人,再送点东西能搞定90%,剩下的也用不着去费心思了。
7、人越多的场合,越要慎言谦逊守礼,自以为比别人聪明,动了趾高气昂摆谱就能斩获尊重的想法的,在众人眼里只是个小丑。
8、越级汇报,是个核武器,伤人还是伤己看你操刀水准。
9、千万不要干挡人财路的事,背后那一双双吃人的眼神,已经意念屠杀了你无数次,难保某天不会成为现实。
10、色字头上一把刀!时代再变,洁身自好永不过时,纵观古今包括眼前,你数数多少有钱有势的,最后都栽在了一个婚外女人的肚皮上。
11、(说个玄学的,不信就听个乐)遇到野生动物、宠物拦路,不要硬闯,适当等等或绕个路,万物皆有灵。
12、学校告诉你要努力,社会告诉你要努力,领导告诉你要努力,其实你早该活明白:开心健康、父母安好,才是一世为人的生命之重,有余力可以再去谈努力,不要本末倒置。
13、职场上,不管对方多诚恳的问你批评意见,千万不要傻傻的一股脑说出来。
14、守住你的原则,记得存有边界感,但你是个成年人,更记得要远离垃圾人,跟他较真你可能会丢命。
15、教父柯里昂说,永远讲道理,不要威胁!否则一旦威胁没达到效果,就没人再怕你了。
16、如果你想夸人,多在背后说有奇效。
17、这个时代赢家通吃,你有一项你精通,但别人不会或者不精的技能,圈内自会帮你塑金身,所以无用的社交,能推就推。
18、你要做一个有深度的人,不要只听对方说话的内容,要搞懂ta这么说的目的,这有助于你思维段位的升阶。
19、对方尊重你,多半是因为对方nb。
20、施恩不图报是真善,要行善施恩就不要图报,要么宁可不施,一定不要沽名钓誉,活成了别人口中的岳不群。
21、男人到30岁,往后就得开始多谋后路,比如改变收入结构,提前应对某些行业的中年危机。普通人一生的高光,并非是攀上那权欲巅峰,而是保护了父母妻小,在变数种种的未来,让家庭有更高的下限和容错率。
22、办公室抽屉里放点口香糖、小零食,能避免你不想求人又需要完成任务的囧境。
23、你比别人优秀一层楼高,ta会眼红孤立甚至打压你,当你优秀到足以狠狠碾压,你才能被其仰望尊敬,所以平日里低调沉住气,不要炫耀小成就。
24、恨人有,笑人无是人性,回家了不要显摆你在外的风光,只有你父母才真心希望你过得好,所以你明面卖惨让邻里心里好过,他们平日里才会让你父母好过。
25、你再上头,也不要做捅破窗户纸的那个人。
26、越珍惜和你的关系的人,越不会轻易跟你开口借大钱,除非穷途末路,因为彼此都清楚,一沾钱,再好的关系也容易变味。
27、成年人应该了解一些人性,一旦出现有悖于人性之事,比如有人教你赚钱,你得好好掂量,到底是谁想赚谁的钱。
28、懂得感恩之人可深交,你也须投桃报李,珍惜就好,总喜欢占你便宜之人,不要撕破脸计较,远离就好。
29、自卑损能量,自负败人品,两个极端之间的分寸,就是一生要修习的课程。
30、我既不主张轻信别人,也不夸大危险导致被害臆想,但是控制风险必不可少,该拒绝的时候就要果断,不好意思只会害了你。
一女同事手艺很好也很漂亮,有次聚餐,上级提出有空去她家品尝手艺,当即被女生拒绝。不管关系再生再熟,从源头掐灭了隐患。
Harry老头子,在丛林的河道里淘金多年了。
很多年了。
向导说快十年了。
Harry说快十年了。
他原来有一块玉米地,后来地里发现了铜矿。
头人告诉他,那块地酋长划给中国人了。
Harry拿了补偿150美元,失去了他的玉米地和铁皮房。
Harry带着全部家当,步行五十多公里,投奔他远嫁的女儿。
女儿家也没有多余的房子,一家五口挤在一栋茅草屋里。
Harry的女婿要喝酒,但是Harry的女儿没有钱,于是女婿打了女儿。
Harry先生很难过,给了女儿女婿全部的150美元,希望女婿不要打女儿,然后搬到丛林的河边淘金,已经快十年了。
Harry先生每天6点起来祈祷。
然后洗一下脸,吃一点昨晚剩的冷而硬的玉米面。
再吃一点盐。
如果捉到蛇或者猴子,就是高兴的日子,他就有肉吃了。
Harry先生会找浅一点的地方,先清理杂草,覆土层和石头,然后挖河沙,以前他一天可以挖出来1吨河沙,现在他工作到太阳下山,只能挖出来很少的河沙了。
因为含金沙层上的土,越来越厚了;可以在浅层挖到砂金的地方,越来越少了。
Harry先生不愿意说得是,他的身体也越来越差了。
他今年6月份,试着挖一个3米的深坑,成功得到了几颗大的砂金,但是随之而来的塌方差点要了他的命,并让他损失了一把铁锹。
Harry先生把砂金卖给印度人,勉强买了把新铁锹。剩下的钱甚至不够他买一袋盐。
他想起了十年前给女儿女婿的150美元,想要拿一点回来去买玉米面。却又看到女婿在打女儿。
Harry先生不知道该怎么帮助女儿,他去老朋友家里,借了一些豆子煮着吃,希望明天的砂金会有个好收成。可以及时偿还这笔债务。
但是,今天Harry先生感觉关节很疼痛,浑身没有力气。应该是疟疾,反反复复的疟疾。
他挖了十年砂金,也没买得起药的疟疾。
他挖了十年砂金,每次卖完都只够买一点食物和盐。
他挖了十年砂金,每次攒一点钱,铁锹就坏掉,他不得不再买一把新的。
他挖了十年砂金,他只想攒一点钱,再回自己的玉米地看一看,看看那个地方还在不在。
今天他把工具扔在了河岸上,晒着太阳,这让他感觉暖和一点。
这个星系的恒星,也确实将光线洒在丛林,老狗和Harry先生身上,红外线辐射带来一点热量,这让他感觉暖和了一点。
几个中国人,走了很远的路,来到Harry先生的河边。
听了他漫长的故事。
给了他大概7美元,让他可以买一点药和食物。
告诉他,这里也要被划为开采区了,也许中国人可以给他一份工作。
这让Harry先生高兴起来。
好像这句毫无根据的承诺,
让他许久以来的勤勤恳恳老老实实,终于有了回报。
又想起越来越贵的铁锹,
又想起快十年没有回去的玉米地,
又想起被家暴的女儿,
又想起自己贫苦而困厄的一辈子,被人说是因为他自己懒。。。
他的微笑的眼睛忽然蒙上了一层暮霭。
(本回答有真实非洲原住民原型,并非虚构。)
内心被恐惧封印的人都有这四个问题:
1、玩,玩不尽兴,心里总有种罪恶感;
2、学,学不进去,心里总有种烦躁感;
3、干,干不尽心,心里总有种无力感;
4、睡,睡不安心,心里总有种焦虑感。
总而言之就是焦虑、烦躁、不安、难受,敏感脆弱、脾气暴躁,情绪低落、身心疲惫,心力交瘁,歇斯底里,无处可逃,就剩半口气吊着,活着都费劲,什么不做都觉得好累,只能没完没了的刷手机缓解痛苦。
为什么会这样?
底层原因是从小缺少陪伴、缺少帮助、缺失重视、缺少认可、缺少理解、缺少支持,同时被打击、被挑剔、被嫌弃,被当成出气筒,怎么做家人都不满意,呼吸都是错的。
怎么破?
把心打开,看见自己。看见内心的痛苦、创伤、包袱,通过【爱的疗愈】刻意练习补缺失、疗创伤、卸包袱把四个内在小孩养大,建立安全富足自由强大的内心世界。
这个时候自立、自信、自我、自爱,自强不息,才能逢山开路遇水搭桥,一往无前,越挫越勇直到成功。
当内心被恐惧封印的时候,你做任何事会自动聚焦在恐惧上,然后现在担心害怕里,头脑上演各种灾难性画面,还没开始做事已经被恐惧打败了。
焦点一直放在担心害怕上,根本没有聚焦在怎么把事做好,怎么把事做成功。因为焦点不在事上,在怕上,自然事情肯定不会成功。事情不成功加深了对做事的恐惧,人生进入死循环,完全被恐惧封印动弹不得。
为什么会这样?
这是因为从小被吓大的,从小到大受的教育全部是恐吓教育,威胁教育,你不好好上学,将来要饭。你再不听话,不要你了。这么简单的事做不好,真是个废物。
各种威胁恐吓,每个结果都是你无法承受的后果。导致我们潜意识非常害怕失败,非常害怕犯错,所以总是担心害怕失败,犯错,内耗精力。
怎么破?
把心打开,看见自己。看见内心的恐惧,通过爱的疗愈补缺失、疗创伤、卸包袱把四个内在小孩疗愈养大,建立安全富足自由强大的内心世界。
这个时候我们才觉知大,自己是大人了,不管做对做错都是安全的,不管成功失败都是安全的,自己有能力对自己的行为负责。
只有我们知道一件小事的对错成败不是决生死的结果,我们是可以承受这件事带来的后果的,这样我们才不会担心害怕结果,我们才会聚焦怎么把这件事做好,把焦点放在怎么把事做好,而不是担心害怕做不好。
中国经济的发展模式并不像所谓经济学家说的那样高大上,更没有什么经济学领域的创新,无非是透支老百姓未来三十年的收入全民买房拉动GDP的快速增长。经济起飞点是2001年加入WTO之后,出口增加、工厂增加、就业机会增加及贸易增加。那时就业岗位大于劳动力供应,造就了收入的上涨,老百姓就有了点钱。于是需要让老百姓把手里的钱花出去,产生GDP。
怎么才能让老百姓把钱花光成为难题,因为中国的第二次分配几乎没有,老百姓不得不大量存钱以备不时之需。这种情况下让老百姓花钱,产生GDP最大化是相当困难的。GDP最大化需要把所有的存款用于消费,最完美的方式是举债消费透支未来的收入。当时的老百姓对于买房并没有什么热情,这就需要通过一些手段来刺激买房的热情。2021年1月前华安基金首席经济学家林采宜在演讲中不小心说了实话“把钱花光,为国争光。爱国主义怎么爱呢?很简单,花钱就是最好的爱国方式。”当然这样的言论必然会承受网民们的怒火。
刺激老百姓花钱的手段:1)开始建立公积金制度,就是把老百姓收入的一部分强制扣留放入公积金账户,只能用于买房。于是公务员事业编率先开始买房,成为最受益的群体,因为房地产就是击鼓传花的游戏,2022年买房的人几乎成为最后的接盘侠。2)新闻舆论与影视作品疯狂地开始鼓吹结婚”新三大件”,买新房成为结婚必备的条件。男方没有买新房就没有结婚的资格,形成著名的“丈母娘”经济。这股风气俨然形成道德绑架,仿佛谁不买房谁就有罪,购买属于自己的房子成为攀比的标配。
3)大搞城市化建设,迫使农民进入城市的方法就是降低进口农业税,进口农产品有很大部分都是零关税,这就导致国外农业强国大量低价的农产品进入中国市场,对本国农业进行价格战,尤其是大豆或猪肉。因此农民开始入不敷出,搞农业挣不到钱,农民只能大量进入城市打工形成了农民工群体。那时制造业开始腾飞,工厂急需用人,因此农业也必须挣不到钱,农民工必须进工厂,唯有如此才能保证大量劳动力进城务工,形成人口红利。
4)大量的农民工进城就形成了一大批购房的刚需,但是依然会有大量农民工不想在城里买房,习惯回老家建房。于是又增加了一个设定:农民工子女只能回原籍上学,因为没有户口。这就导致子女如果跟着父母进城就没有办法上学,这就形成了留守儿童这个群体。但是买房就可以解决户口问题,于是更多的农民工咬牙在城市买房。把房子、户口和教育绑定,就制造出了大量的购房群体,中国经济学家都是“鬼才”。
在这个过程中房价开始快速上涨,由此房地产就有了投资属性,进一步催生房价暴涨,而房价暴涨又可以加杠杆,房子就拥有了金融属性。房子最终与婚姻、户口、教育和医疗等刚需绑定在一起,买房成为中国普通人的信仰。因此全体中国人民开始贷款买房,这就导致GDP暴涨形成中国经济的奇迹,因为是全体老百姓用未来三十年的收入在拉动国内消费。到了今日,大多数人把未来三十年的收入及“六个钱包”掏空,都花在了房地产上成为最后的接盘侠。
大家都没有钱再买房了,那么GDP还能依靠什么增长?于是有专家建议:房贷延长到40年。原则上所有人再多贷十年款,依然可以拉动内需产生GDP,这样做显然是竭泽而渔。中国人花光了未来三十年的钱,内需开始持续萎靡,出口方面欧美又正在与中国脱钩,然后是基建的边际效用递减,造成失业人口大量增加,内需就会持续低迷。这一次的经济萧条是从企业到个人全方位的低迷,国内经济进入通缩周期,也进入了还债周期,如果经济没有新的增长点或者开拓新市场作为倾销地,这个衰退的周期将会是会很漫长的。
房地产是中国经济奇迹的助推器,一旦熄火,整个经济将会猛然失速。不买房等于货币失去流动性,经济将陷入持续性衰退,从而引起社会的不稳定。
【NV-00】Nvidia硬件介绍和CUDA编程入门
该处的线程和 CPU 上是不同的概念,CPU 上一般是执行不同任务,GPU 执行的这是相同的核心函数,是同时执行。当然 GPU 上每个线程的 thresholdidx 是唯一的。
Device:指的是 GPU 芯片。Grid:对应 Device 级别的调度单位,一组block,一个grid中的block可以在多个SM中执行。Block:对应 SM(Streaming Multiprocessor) 级别的调度单位,一组thread,同block中的thread可以协作。Thread:对应 CUDA Core 级别的调度单位,最小执行单元。上一篇文章介绍的:CUDA函数用的<<<x,y>>>: x 即是grid_size, grid 的 block 数量; y 表示block_size, block 的 threshold 数量。因此<<<2, 3>>> 即表示分配2x3=6个线程运行某一核函数。
Grid 和 Block 可以用多维矩阵表示,按照上图演示,定义线程的方式如下,z维度默认为1:
CUDA内置了一些变量方便我们调取线程的坐标:
threadIdx.[x y z]- 线程坐标。框架图中, Thread(2,1) 的 threadIdx.x = 2, threadIdx.y = 1。blockIdx.[x y z]- block坐标。框架图中, Block 的 blockIdx.x = 1, blockIdx.y = 1。blockDim.[x y z]- block的维度,表示一个block中包含多少个thread。框架图中,blockDim.x = 5, blockDim.y = 3。gridDim.[x y z] - grid的维度,表示一个grid中包含多少个block。框架图中,gridDim.x = 3, gridDim.y = 2。理解线程的索引方式非常重要!特别是后面用线程对存储进行操作。其中xy表示的和数学的矩阵坐标是相反的:x表示横着数第几列,有表示竖着数第几行。
网格大小(gridDim):
x: 2^31?1y:65535z:65535线程块大小(blockDim):
x:1024y:1024z:64另外,还要求线程块总的大小,即 blockDim.x、blockDim.y 和 blockDim.z 的乘积不能大于1024。也就是说,不管如何定义,一个线程块最多只能有1024个线程。这些限制是必须牢记的。
图的阅读可以看出硬件的组成关系,也可以看出软件和硬件的对那个关系。这里解释下后者:
一个 thread 一定对应一个 CUDA Core,但是CUDA Core可能对应多个 thread。一个Block内的线程一定会在同一个SM(Streaming Multiprocessor,注意不是后面经常提到的Shared Memory)内,一个SM可以运行多个Block。每一个block内的thread会以warp为单位进行运算,一个warp对应一条指令流,一个warp内的thread是真正同步的,同一个warp内的thread可以读取其他warp的值。思考:为何我们需要设计 Block 呢,增加一个抽象,增加了复杂度。
简单回复:
硬件设计架构决定的;没有block的,会导致全局的同步开销过大,这么设计使得可扩展性更好;加载核函数将Grid分配到一个Device根据<<<..>>>内的执行设置的第一个参数,Giga threads engine将block分配到SM中。一个Block内的线程一定会在同一个SM内,一个SM可以有很多个Block。根据<<<..>>>内的执行设置的第二个参数,Warp调度器会调用线程。Warp调度器为了提高运行效率,会将每32个线程分为一组,称作一个warp。每个Warp会被分配到32个core上运行。
线程索引和数据地址的转换。CUDA核函数工作时,所有线程同时执行,以下面并行加法为例,需要为每个线程匹配对应的数据地址,因此需要将线程索引转换为数据地址,方法如上图。
N为数据维度。最大可配置的Block大小为1024,详细可按照如下命令查询硬件:
因为block内的线程是按照warp来调度的,所以blocksize尽量设置为32的倍数。
提问:block_size(尖括号第二位)不是32倍数的后果是什么,也可以通过的
解答:正确使用了内置的索引和形状变量(threadIdx, blockDim; blockIdx, gridDim)不会有正确性的影响。但可能会导致性能下降。
追问:改成了33就分成2个warp?
解答:是的。超出哪怕1个线程,也会分配一个warp(浪费31/32的潜在执行能力)。
当数据过大,超过线程数的时候,可以采用如下方式处理:
其中index为线程匹配的数据地址(下面会详细介绍),stride为总线程数。
CUDA函数流程:
利用数据索引编写CUDA函数;利用cudaMalloc为变量分配CUDA地址;cudaMemcpy 将数据从内存拷贝到GPU;<<<grid_size, block_size>>>调用CUDA函数;cudaMemcpy 将数据从GPU拷贝回内存;cudaFree 释放资源。代码的执行情况:可见 相关链接 的github代码库的 02_2.2。
1)每个block应该申请多少个线程呢?
底层是以warp为单位申请。 如果blockDim为160,则正好申请5个warp。如果blockDim为161,则不得不申请6个warp。
2)如何设置Gridsize和blocksize呢?
对于一维的情况:
block_size=128;
grid_size = (N+ block_size-1)/block_size;
(没有设成什么值是最好的)
注意:代码可见 相关链接 的github代码库的 02_2.2。
github代码库:https://github.com/yifanhunter/CUDA_on_ARM_learning