《深入理解计算机系统》一刷(2023.10.16)
这本书很深,对于早已失去了专注力的我来说,想一遍就消化掉是不可能的,只看文字不看视频不去实践一定会消化不良。暧昧一点吧,找不到好的词汇形容。
走马观花也多少能记住些东西,先说一下第一块难以理解又重要的地方是,其实每个地方都很难全部理解,但是对我而言,更重要的是现在大体上把说不通的点讲通。
流水线是一个很难掌握的点。
首先是和洗碗筷差不多,任务是一个一个来的,即便核很多,如三个核,那要三个时钟周期才能让三个核都进入工作状态。这个核,用自助餐厅的不同种食物代替吧。
之后是,每个核工作在同一个任务的不同阶段,看起来是并行的,但彼此之间还有有细小的时间差异。
还是那个洗碗洗筷子模型,系统的吞吐量受到最慢阶段的速度所限制,流水线是一步一步来,在一个时钟内,即便一个阶段被完成,但它总是需要等待前面的阶段或者后面的阶段完成,才可以进行跳转。所以最慢的阶段限制着流水线速度。
切分切分切分,最后限制速度的是寄存器的读写速度。
如果加入前后顺序的反馈,那么最后一步产生的反馈信息要给第一步,这是两个过程之间传递反馈信息。需要做修改。将seq变为seq+,动态计算pc。(完全不知道自己在说什么了)
我只能理解为,各个阶段需要配合,需要等待把每个步骤时间对齐,对不齐就容易产生用过去的信息计算当前的状态,得到的是错误的答案,这错误有大有小,但一定是不可以的。
然后这种一有冒险就停止等待的做法可能过于缓慢,引出了用转发来避免数据冒险。
本来我要等你写完我再读,可是不如你先直接送过来,这样对于整个过程耽搁得就比较少,写与送的过程应该是同样速度的,那么我觉得节约的时间是读的时间。唔!
两个过程之间没法传送数据了,这时候用暂停与转发结合的方法。(有点不懂)
将一个数连加两次和加一次一个数的两倍,结果可能会不一样,不排除两个指针指向同一个地址的情况,比如由浅复制产生的对象的某个成员变量,加两次原来数会变为原来的四倍,可能这样加不了,他或许还没有访问权限。但加一次两倍就变为原来的三倍。因此这两个不可以相互代替。
对内联函数有了更清楚的认知,将指定函数体插入并取代每一处效应该函数的地方。这不是宏定义。
函数在形参与实参结合时,最好用函数内的变量记录一下实参的变量,相当于把别人的书抄了一遍就放在家里用,否则,每次循环都使用的话,每次都要跑过去抄同一个字,再跑回来运行。测数组或者字符串长度测一次就记录下来,不要把测试函数放在循环里。减少调用的开销。
记住for的短路啊!
但如果一些数据你可以调用,但是不能知道它的值是什么怎么办呢?应该是不可能的,可以用,就可以读,可不可写才是安全性的重点吧。或许。
我不记得卡诺图是如何化简的了,但是,会不会他有化简指令的能力?把100个指令同时塞进去,经过化简变成几个指令,这不就是一种优化吗?或许。
我明显是对逻辑的理解更深刻一些,对于硬件是如何工作的理解不多。
把重复的部分抽出来打包。我现在脑袋里想的就是这个。
溢出处理也是一个安全部分较为重要的地方,难哦。
改变计算次序而提高运算速度或者运算精度的方法,我想了两个,一个是秦九韶;一个是把数据排序后再做计算,可以减少大数吃掉小数后的损失。
学到的是,当对需要不断更新的值做乘法时,可以把已知部分括起来,让他们先行计算而不需要等待这个更新值,可以降低延迟。
用冒号问号的句式做数据交换,是一种基于条件数据传送的手段。它有好有坏我不好掌握,但是,应该先好好习惯冒号问号的代码书写格式。
那种预测机制也不明白,只能举个应用场合的例子,当一个数不断自加直到被上限挡住为止,这个过程预测出错只会出现在最开始和结尾,中间一直是否,预测起来不会出错。
更深的地方就挖不动了,先这样。
如何更快?硬件多数时间都在做加减乘除,再干活,而不是把过多时间浪费在跑来跑去。
增加限制条件,然后去掉冗余的限制条件。
放东西就是这个道理,越常用的越要放在能快速拿的地方。我们的世界不是游戏里抽象的仓库,而是具有一个存储的层次结构,有远近难易之分。
有记忆的统计来自于局部性,它认为已有之事后必再有,已行之事后必再行。我之前觉得有道理,后来觉得也未必,有些东西摒弃掉了就是摒弃掉了,可能会在别的个体上持续发生,但在单个个体上未必。这有点算是抬杠了,总之呢,局部性可以大大提高性能。
无条件跳跃可能导致死循环啊,或者莫名其妙鬼畜起来了。虽然对于复杂的过程来说,未知错误是难免的,但还是尽可能把会出错的地方修补一番,然后在关键的地方用try与catch。
映射表的查找方法,如果虚拟内存和物理内存之间的映射表的查询方式是顺序查找,映射表又很长,查的位置不满足局部性来回跳,那时间就会花费很多,这么大的宏观的事可能不是我该考虑的,我就把他缩小吧。要是我建立一个用于存储和查询的表,我就会尽量让他们的序号有一定的意义,至少可以让我或者程序估计,要查的东西在前一半还是在后一半,哦我想起来了,这是不是设计了主键的排序呢?我真是笨蛋。
除了排序也可以分级,手动地告诉代码,要找的东西在上一半还是下一半,分两级就更加好找了。(过于幼稚)
层之间的关键字可以用门电路连接,这样的话很客观安全,但是是牺牲了物理空间换去来速度伤的性能。没有两全法的。只有取舍。
借用必须要有借用恢复,有点像中断。
需要保持状态的块,还是很经典的一句话,出门要有锁存,进门要有缓冲。
去掉冗余,相同的部分只写一次,这就是c++的优势哦,不,是共享的优势。
创建一个垃圾堆,或者垃圾堆也可以临时使用,多想想如何把现实中的概念应用到虚拟的领域,这样或许我们分不清梦境与现实之前,就已经分不清虚拟与现实了。
大块与碎片的概念也很好,整可以碎,碎不可以整也。
相邻的块要比破碎的块更好用,不相邻就要花费一部分出来连接破碎的块,可能也需要花时间挑选出合适或足够的块们。
&有和没有区别很大,需要重视。
显示地初始化为0十分重要,要注意。
动作的前面都会加入一个隐含的形容词,请求。
知其然容易,知其所以然难。我知前者少,知后者更少,怎么会说话呢?不好意思啦。
虽然看不懂的多,但还是有收获的,加油!
或许会二刷吧。或许。