百科问答小站 logo
百科问答小站 font logo



cpu —>内存—>硬盘这种方式是不是更慢? 第1页

  

user avatar   s.invalid 网友的相关建议: 
      

不是。


讨论这个之前,你得先搞清楚两个概念:带宽和延迟。


比如你哥们儿有1个T的那种视频,你想要来看看。


现在你们有两种方案。

方案1,你哥们把自己的硬盘拆下来,坐公交到你家,插你电脑的SATA口对拷。假设坐车到你家得一小时,拷贝需要一个小时。那么一小时后你就能坐下来看片儿了。

我们就说,这个方案的数据读取延迟是1小时,带宽是0.5T/小时。


方案2,你哥们让你打开个软件,通过上传带宽为8Mbps的光纤给你传过去——也就是每秒1M字节,8M位。

那么1T数据就需要传1000X1000=一百万秒。也就是277个小时,大约11天。

不过,在数据传输的同时,你已经可以打开软件看片儿了。

我们说,这个方案的数据读取延迟是0,但带宽只有上一个方案的1/554。


类似的,硬盘文件读取很麻烦。你得先把磁头挪到位(寻道时间),然后等需要的扇区转到磁头下,然后才能读取数据。这个时间一般需要十几个毫秒。换句话说就是硬盘延迟很大。


同时,硬盘是机械部件,读取是一个盘面磁场和磁头相互作用的物理过程,这个过程不可能比电子器件里面的电子迁移更快(这就是SSD硬盘替代传统机械硬盘的原因)。因此1T的数据往往需要个把小时甚至更长时间才能读完,也就是只有几十M字节每秒。换句话说就是硬盘带宽不足。

zhuanlan.zhihu.com/p/19


相比之下,内存条的数据读取延迟就非常小。比如DDR4的延迟就只有5.714285714285714e-9秒(数据来自:zhihu.com/question/3091),也就是5.7个纳秒(千分之一秒为一个毫秒,千分之一毫秒为一个微秒,千分之一微秒为一个纳秒),比硬盘快上百万倍。

同时,DDR4的带宽可以达到几十G字节每秒,比硬盘大差不多1000倍。


那么,现在,你还觉得内存+硬盘比直接硬盘读取慢那么几百万分之一很重要吗?


实际情况还要复杂一些。


比如说,硬盘寻道延迟特别大,如果你这里读点那里读点、使得它不停寻道的话,它的带宽就只剩0.5M/s左右了(这种工作场景就是“随机读写”);反之,如果寻道一次就连续读,那么它的带宽可以达到几十兆每秒。

类似的,DDR4内存读取潜伏期为16个时钟周期;如果每次读取你都来回跳,那么每次你都得等16个时钟周期,它的带宽就没法看了;反之,如果你顺序读下去,这16个时钟周期的潜伏期就可以免了。


同样的,CPU的时钟又比内存快了十几倍(可能更高也可能更低),每个时钟周期又能执行两条以上指令;那么当它停下来等内存的时候,就少执行了至少几十条指令——倘若等硬盘,几亿条指令的执行机会就白白放弃了。


因此,在高速设备和低速设备的交界面处,我们会设置一种叫“缓存”的东西——也就是其他答案提到的cache。


通过缓存,我们可以给慢吞吞蜗牛一样的内存(或者慢吞吞岩石一样亘古不动的硬盘)发一条指令——把你地址XXX的数据准备好,等下我来取!


于是,经过16个时钟周期,DDR4内存就把XXX开始的数据源源不断的送进缓存(为什么要源源不断呢?因为在大多数场景里、尤其在程序员的刻意安排下,数据是尽可能按顺序大量读取的。这就叫缓存友好,可以有效提高软件执行效率),同时通知CPU:数据准备好了!过来读取吧。

类似的,硬盘也会先把数据放进缓存(硬盘线路板上面的缓存),然后这些数据进一步放进内存缓存起来、最终还得在CPU的一二三级缓存里缓存。


这一切一切,都是为了提高整体执行效率。

换句话说,硬盘相对于内存太慢了,相比于让内存/CPU这些快手停下来等这只蜗牛,不如放任不管,等蜗牛爬到地方再通知CPU处理。


甚至于,有鉴于蜗牛实在太慢,如果它准备一点CPU就处理一点,这样打断CPU的工作就容易引起缓存失效、指令队列失败等后果,耽误CPU几百纳秒的时间——这是得不偿失的。

因此,我们往往会搞一个比较大的磁盘缓存,让蜗牛硬盘慢慢准备数据。比如先让它准备个几秒钟,存了上百兆数据,这才值得打扰CPU一次——然后CPU花上几个毫秒搞定这些数据之后就可以回去继续忙自己的,让蜗牛硬盘继续慢慢攒数据。


注意这些例子都是关于读取的;但实际上,写入内存/硬盘同样是慢如蜗牛。因此CPU就会“不负责任”的把数据往缓存一丢:“蜗牛!把这些数据拿回去存了!我忙别的去了。”

这就是电脑不能拔电源关机、U盘不能一看文件拷完就马上拔掉的原因——CPU仅仅是把数据丢进了缓冲区而已,丢完就认为自己任务完成了。它太快了,实在不耐烦也不应该等这些蜗牛完成存储工作。

因此,你需要点弹出U盘或者通过关机命令,让CPU回头确认下这些蜗牛是否已经把丢给它的存储工作搞定了,这才能执行拔出/关机操作。


正如前面提到的,任何高/低速设备的交界面都需要一个cache,这样我们才能让高速设备充分展示自己的能力。

比如说,因为内存太慢,所以CPU不得不搞个三级缓存等蜗牛内存准备数据;然后二级缓存再等蜗牛三级缓存,一级缓存等蜗牛二级缓存——最后,CPU里面的寄存器才是终极速度冠军,大量计算优先在寄存器里搞定,非必要不去访问一级缓存;一级缓存没有才访问二级缓存,然后是三级缓存……

这里同样存在“数据存储不及时”问题,术语叫“数据一致性问题”。我记得某些0day就是利用数据一致性算法的漏洞完成攻击的。

扯远了。


总之,CPU->内存->硬盘的确比CPU->硬盘更“慢”,但这个慢甚至比不上你敲键盘造成的震动透过桌面对硬盘磁头造成的影响、或者你插拔手机充电器造成的电压波动对硬盘寻道的影响。

这个“慢”相当于硬盘延迟从10个毫秒变成了10.000000x毫秒,完全可以忽略不计。

但通过内存缓冲,我们就可以避免CPU迁就硬盘的低速度;就好像通过CPU三级cache避免它被内存的低速拖累一样。


这个好处是如此巨大,以至于我们宁可稍稍增加内存/网卡/硬盘延迟——比如,刚刚读完一个扇区是不应该打扰CPU的,起码读上一两兆字节的数据再喊CPU过来,计算机的整体执行效率反而更高。

换句话说,我们不仅不应该纠结那0.000000x毫秒的延迟,反而应该主动再添加上几个甚至几十个毫秒的延迟,等硬盘准备的数据多一些、这才值得让CPU过来处理一次。

蜗牛硬盘的数据被充分缓存、具有很高的缓存命中率之后,计算机系统的整体性能才能得到优化。

举例来说,Linux会尽量把你的内存用作缓存,这样才能确保程序运行效率最优化。

当然,当程序需要更多内存时,它也会主动退还一些缓存,不会造成过早的OOM(Out Of Memory)。

Windows到vista/win7时代后也开始这么做。这些可以在资源管理器里面看到,其中的“备用”就是这部分内存。


当然,你可能会问:为什么一定要搞的这么复杂?直接用一级cache当硬盘用不好吗?


答案是:越快的硬件,其制造成本就越高。

比如,100来块钱你就能买到1T的硬盘;但拿来买内存条就只能买到4~8G——内存条的价格是硬盘的100甚至200多倍!

而这个价钱,去买L1缓存大概能买1M不到,买寄存器或许能买几十个字节……

相比之下,多级不同速率的存储方案就能兼顾容量和速度,代价仅仅是体系复杂一些而已。这显然是个性价比最高的方案。


当然,有些场景下我们必须海量超高速存储。比如有些服务器就有1T以上的内存。嗯,掏钱就是,几万块钱而已;但如果你想要1T的寄存器……慢慢想吧,这可不是拿钱就能摆平的事。


好吧,纸糊惯例,再驳几个奇谈怪论。


1、CPU究竟能不能从硬盘读取数据?

能。


至少自8086开始,x86 CPU就有一套专门的外设通讯指令in/out;同时,它的外设和内存分别编址。


什么意思呢?

比如说,硬盘或者网卡或者软盘有数据了,CPU怎么拿到这个数据呢?是不是其实CPU压根不知道有这个外设、需要先通过某个机制把这些数据搞进内存、然后CPU处理内存数据、假装自己知道存在硬盘?


这是外行的误解。


事实上,硬盘在x86 CPU的IO口编址为0x80(差不多20年的记忆了,可能不准);当我们想从硬盘读取一个字节时,可以往0x80写一个命令字。比如,out 0x80, 0x7001 (假设0x7001意思是“传输一个字节”,这些指令我更记不住,别当真),这个命令使得IO地址引脚选中0x80端口,然后把0x7001放到IO总线引脚上。

实际上,这个过程更为复杂。它应该是先发寻道指令0x7007,参数0x50(意思是把磁头移动到编号0x50的磁道上),再发送扇区定位指令0x7009,参数0x1A(意思是读取第0x1A扇区的内容),然后发数据请求指令0x7001,参数是需要的字节数……


当硬盘发现自己接到了这些指令时,它内置的一颗微型数字逻辑电路芯片(现在几乎都是CPU了)就会执行一段程序,完成磁头寻道、扇区定位、数据读取(先缓存在硬盘内部存储器里)等动作;这些动作做完后,它触发一个中断;然后CPU再使用in 0x80指令把硬盘准备好的数据读到CPU——再然后,通过数据总线把这些数据存入内存。


换句话说,CPU不仅能够从硬盘读取数据,实际上,硬盘数据还必须先到CPU里绕一圈、然后才能放进内存。


即便如此,硬盘数据仍然要先存进内存、然后再给用户程序使用。

这是因为硬盘实在太慢,因此“先积累一定量的数据再开始处理”总是优于“直接从硬盘边IO边处理”。

只不过,这个缓冲动作对用户透明,因此大多数人不知道而已。


当然,有些CPU把外设和内存统一编址。比如约定0x01到0x1FFF是外设地址,再往后才是内存地址。这样可以统一内存访问和外设访问指令——但换汤不换药,程序处理时仍然要这样一套一套的。


我们可以看到,硬盘上的单片机系统和CPU之间也有指令交换;这套指令或许没有CPU的二进制指令复杂,但也没那么简单……

那么,CPU是如何知道硬盘网卡之类外设可以接受的命令字的呢?又如何知道这些命令字的含义呢?如果硬件厂商发明了新的存储机制(比如SSD),没法再用磁道/扇区管理了呢?此时是不是控制指令全都不一样了吗?CPU怎么知道该用什么指令?


答案是:CPU不知道。所以我们需要“驱动程序”。

借助驱动程序,我们才可以“一切皆文件”,比如告诉硬盘文件,我要读若干字节到你的XX地址。

硬盘/软盘/光盘/网卡厂商编写的驱动程序需要把这个命令翻译成前面我提到的in/out指令序列,从而指挥硬盘完成任务。

这就是为什么很多硬件不装驱动就不能用的原因。


前面提到“硬盘数据需要CPU用IO指令读入内存、然后等执行程序时再从内存读取”——这个弯弯绕实在太多了,是吧?

因此,后来硬件厂商就另外搞了一颗比较弱的微型CPU,让它代替那个背着巨大散热器的、死贵死贵的大佬CPU,专门处理“在IO口和内存之间搬运数据”的工作。这样当硬盘数据准备好时,大佬CPU(i5/i7/锐龙等)只需告诉这颗微型CPU“你把数据存到内存地址0xAAAA和0xBBBB之间”,微型CPU就替它完成了硬盘->CPU->内存的搬运工作(写入过程也类似)。

这颗专门用来代替主CPU、完成外设和内存之间的数据搬运工作的CPU,就是所谓的“DMA控制器”。



2、硬盘分区格式影响CPU访问数据吗?

答案是:硬盘分区格式是什么?能吃吗?


和你在内存中搞的链表一样,它仅存于你的心中,你的程序中——如果你老糊涂了,把链表当二叉树访问搅的乱七八糟,CPU也不会知道。


同样的,硬盘对CPU来说就是一个巨大的线性存储区;是我们为了方便自己使用,这才把这块存储区用fat/ntfs/ext之类格式建立了索引。

于是,当我们需要访问“E:学习资料考研资料资料备份日语xxx.avi”时,这个请求会先交给文件系统驱动,这个驱动把它翻译成“读写硬盘2的第二个分区的第xxx扇区的一组请求”,然后再调用硬盘驱动翻译成一组具体的指令字,这才能完成文件读写操作。


——没错,驱动也可以分层。底层驱动直接和硬盘打交道,把它虚拟成一个平坦的线性存储区;上层驱动再把它虚拟成ntfs格式的文件系统。


如何验证呢?

你可以在Linux下建立一个10G空白文件,然后用mkfs.ntfs之类之类在它上面建立ntfs格式的文件系统;然后,你就可以用mount挂载它,就好像它真的是一个硬盘分区一样。

你甚至可以用fdisk给这个空白文件先分区,然后用mkfs为每个分区指定不同的文件系统格式;这个东西同样可以用mount挂载、然后当磁盘使用。

当然,你也可以把它传给kvm,让KVM把它当成虚拟机硬盘使用——没错,你用系统拷贝命令复制这个文件,就可以弄出一大堆不同的虚拟机实例。



你看,硬盘如何分区,这事压根不归CPU管。它连这个分区表是建立在硬盘上、硬盘分区里、硬盘文件上、内存里甚至网线另一端都不知道;但与之同时,只要你愿意,这一切归根结底,每一个字节都要经CPU的手(或者自己直接读取、或者指派给DMA或其他相关控制器读取)——计算机里面抽象很重要,当CPU执行层次较低的抽象时,它就是在一个字节一个字节的IO;但在CPU执行层次较高的抽象(如文件系统抽象)时,它又在的确是在读写文本文件/图片文件(还带权限检查呢)。

就好像CPU可以一边执行病毒程序大肆破坏、一边执行杀毒程序检查/清理病毒一样。对CPU来说无论OS还是病毒还是杀毒软件还是电影播放器,它们都是无差别的一系列指令,只是指令执行时不同寄存器/状态指示器处于不同状态而已。

亦因此,我们可以识别哪些指令是外设访问相关,从而提前截获它、控制它能够访问的区域,这就是XEN半虚拟的工作原理。类似的,新式CPU内置了虚拟指令支持,当处于低权限的虚拟机模式时,使用硬件访问相关的指令就会触发中断,使得宿主操作系统有机会重定向这些操作,从而不需要像XEN那样修改OS内核就能让虚拟机直接在真实CPU上运行、同时还能控制它可以访问的资源。

换句话说,恰恰是因为CPU掌握着和硬件沟通的通道,我们才可能卡住这个点实现硬件支持的虚拟机。以为做了个抽象结果CPU就碰不到抽象前的东西了,那纯属无知。


user avatar   suan-le-ba 网友的相关建议: 
      

这两个游戏都有自己的问题。但严重程度完全不一样。

赛博朋克最大的问题是人力不够,没有人手把愿景在限期内做出来,导致后期狂砍。但从已有的成品来看,CDPR是完全有人才有能力把东西做出来的,只不过没时间做。光影效果,已有的垂直城市设计,以及主线和很多支线任务的演出都有毫不输巫师3的气质,尤其是日本城浮空平台那关,无论是游戏流程还是画面还是音乐,都把类似银翼杀手2047的那种气氛和感受做到了极致。有人说CDPR的人才都跑了,或者CDPR傲娇了开始放水,这并不客观。2077确实是个半成品,主机优化的问题尤其严重,但你关注已经完成的部分,用高配置PC玩,其质量并未令人失望,依然是巫师3的水准。

2077就像是一个优等生忘了做背后的几题的考卷,开天窗导致不及格,但已经做了的题目还是正确率极高的。

谈到E3的demo,单从画面上讲你很难说它缩水了。只不过CDPR没告诉你想要E3画面,就得上3080+光线追踪。。。

我猜想没有光追的话,游戏在大多数情况下也是可以达到光追的效果的,只不过人工工作量会很大,有些地方需要离线烘培,而有些地方需要人工设置虚拟光源。CDPR可能发现项目后期工作量太大搂不住了,就上了光追这个大杀器。。。


至于无人深空,现在口碑很好,但我要不客气地讲,这个游戏到了今天依然是垃圾,只配卖$19.95,打折的时候卖2.95的那种。

Hello工作室自始自终都没有把初始愿景实现的技术能力。

你可以看无人深空进入大气层的技术实现。先是一段飞船进入大气层摩擦发红的特效,然后可以看见地形通过一种非常粗糙、视距很近的情况下刷新出来,并且刷出来的地貌和太空中看到的地貌完全不同。所以从头到尾,hello工作室都没有类似精英危险和星际公民的无缝行星登陆技术。

无人深空更新了十几次,并没有触动这个游戏除了机械刷就没有任何深度的本质。这是一个极其无聊的游戏。但它刷了两年的DLC,玩家也就给他点面子,没功劳有苦劳。它每次更新我都会进游戏看看,但玩不了半小时就会放弃。一是实在无聊,二是它美术设计和渲染水平有限,色彩及其刺眼。比如在母船机库里,到处都是亮瞎狗眼的点状光源,但这些光源不会照亮周围的任何东西,看的时间长了有种不带护目镜看焊接的流泪效果。你说更新了那么久,这么简单的问题都不解决,有什么用呢。游戏中随处可见低级设计的痕迹,比如说有很多行星上有一种可以卖钱的球,这种球没有任何贴图,只有亮瞎眼的纯白色材质,在HDR效果下极其刺眼,但它又不是个光源,放在地上不会照亮周围任何东西。这种打开Blender就存盘的建模初手垃圾素材居然也能放在游戏里,真是活久见。

所以无人深空就像是一个学渣冒充学霸,把期望提得无限高,却每题都答错结果接近0分,被骂,然后花了漫长的时间在那里订正,一题一题的改,最后终于接近30分了,然后获得了大家的赞赏,全然忘记了它改了那么久依然是不及格。

无人深空的贴图我就不贴了,首发的时候真是纯垃圾,基本上是2008年魔兽世界首发的那个水准。现在也依然是垃圾,开个HDR看着眼睛都疼。




  

相关话题

  A11处理器有55亿个晶体管,假如一秒钟设计一个晶体管,那也需要十几年,工程师如何设计这么多晶体管? 
  是否可以将显存提供给CPU使用? 
  如何看待苹果抛弃intel,转向ARM架构? 
  龙芯和英特尔、AMD的差距在哪里? 
  既然华为的SoC是Arm公版设计,那所谓的自主研发体现在哪里? 
  如何看待比 iPad 还大的史上最大芯片问世? 功耗比电磁炉还高有什么用? 
  如何看 intel 4 工艺提前发布,是不是 AMD 给的压力太大,牙膏厂变身喷射勇士? 
  使用内存超过32G(含)的电脑是种怎样的体验? 
  如何看待小米 10 全系标配 LPDDR5 内存? 
  为什么手机储存芯片传输协议速度已经高于sata但是传输速度感觉还是没电脑快? 

前一个讨论
医生是干得越多,收入越多吗?
下一个讨论
一年级的孩子课堂表现出色,也很聪明,但是考试总是七八十分怎么办?





© 2024-12-26 - tinynew.org. All Rights Reserved.
© 2024-12-26 - tinynew.org. 保留所有权利