用纸当内存条还能跑游戏硬核知识轻聊局:从原理侃生活

用纸当内存条还能跑游戏

9分钟 ·
播放数13
·
评论数0

说话人1: 来了啊。先问你个事儿:你电脑内存不够用的时候,一般怎么办?


说话人2: 加内存条呗,预算不够就开虚拟内存,让硬盘先顶着。


说话人1: 那如果硬盘也不许用呢?就给你一沓A4纸、一支笔,你能不能把内存给扩出来?


说话人2: 你今天状态不太对。纸怎么当内存?它一不通电二没电路,数据往哪儿放?


说话人1: 放纸上啊,拿十六进制字符写上去。你先别急着笑,这事真有人完整干成了。这期话题是李坚毅博士整理创作的,内容就是一套"纸质内存"系统——真拿普通纸张当内存条,还在上面跑游戏。


说话人2: 等会儿,就是那种打印作业的纸?那我先问最根本的:内存不是个电子器件吗,怎么就能被纸替代?


说话人1: 这就得先聊虚拟内存。现代操作系统管内存靠"分页":把整个地址空间切成一个个固定大小的块,叫"页"。随便一个虚拟地址,都能拆成两部分,页号和页内偏移量。用大白话说,虚拟地址等于页号乘以页面大小,再加上页内偏移。


说话人2: 来,算一个听听。


说话人1: x86架构的Linux,默认页面大小是4096字节,也就是4KB。那虚拟地址10000落在第几页?你就拿10000除以4096,商是2,余数是1808。翻译过来就是:第2页,页里第1808个字节。


说话人2: 哦!所以地址本身就自带俩信息——第几页,以及页里第几个位置。


说话人1: 对。那程序一访问,发现那一页根本不在物理内存里,怎么办?处理器会触发一个"缺页异常"。正常情况,操作系统内核立马从硬盘交换分区把这页读进来,程序接着跑,你完全无感。


说话人2: 那纸质内存的玩法是……


说话人1: 把内核这活儿给截胡了。Linux有个机制叫userfaultfd,允许程序在用户空间自己注册内存区域、自己处理缺页事件,一行内核代码都不用改。于是缺页一来,程序不找硬盘,直接弹窗催人:去纸上把那页的十六进制数据找出来,敲进来。


说话人2: 等会儿,就不能走正道吗?Linux本来就支持拿文件当交换空间啊。


说话人1: 试过,翻车了。想直接把文件挂成交换分区,结果页面大小对不上,还缺交换分区专用的头结构,死活挂不上。原生工具这条路堵死,才逼出自研用户态缺页处理程序这条路线。


说话人2: 行,那读我明白了,写呢?


说话人1: 写就反过来:程序把改动的数据用十六进制打印出来,你拿笔抄到纸上对应位置。落纸为安,这就算持久化了。


说话人2: 打住,内存里是二进制啊,纸上总不能画一长串0和1吧?


说话人1: 所以用十六进制。这有个特别舒服的换算:一个字节是8个二进制位,一位十六进制字符正好表示4个二进制位。8除以4得2,所以一个字节就对应两个十六进制字符——字符总数等于字节数乘以2。


说话人2: 我验证一个。字母A的ASCII码是65,写成二进制是01000001,劈成高四位低四位:0100是4,0001是1,所以纸上写"41"俩字符,就存下一个字母A。


说话人1: 满分。那32字节的数据,编码出来就是64个十六进制字符,一行写下;后来扩到64字节,也就128个字符,小半张纸的面积。一沓纸,理论上就是一根"内存条"。


说话人2: 但我发现个致命问题。电子内存是随机访问,给地址瞬间定位;纸呢?纸上要写了一百页数据,程序要第87页,你怎么找?


说话人1: 问到根上了。纸没有随机访问能力,只能用"线性页面编号":第一页、第二页顺着写,找的时候人眼顺着翻。寻址时间跟页数基本成正比——寻址时间等于单页查找系数k乘以页面总数n。页数一上去,开销直线起飞。


说话人2: 懂了,电子内存是"直接翻到指定页码",纸是"从第一页开始一页页干翻"。


说话人1: 比喻精准。那这套东西到底能不能跑程序?李博士整理的测试里,第一个上场的是个终端乒乓球游戏。游戏全部状态就8个字节,排成一个状态向量:球的横坐标、纵坐标、水平速度、垂直速度、玩家挡板位置、电脑挡板位置、玩家得分、电脑得分,每样一个字节。


说话人2: 8个字节?编码出来就16个十六进制字符?


说话人1: 对,16个字符落纸上,就是一个完整存档。要存档,程序把这16个字符吐出来你抄上;下次开机敲回去,比分、球速、挡板位置,原样复活。后来还上了个文字冒险游戏,场景切换、物品栏、随机事件全都有,存档时程序干脆把物理内存清空,纯靠纸上数据恢复,连缓存作弊的机会都不给。


说话人2: 这么狠?那人工抄来抄去,没出过错?


说话人1: 出了,而且出了个名场面。有一回录入敲错数据,程序直接段错误崩溃——这大概是头一个由纸张直接导致的程序崩溃。你想,电子内存靠ECC纠错电路自动修比特错误,纸质内存靠什么?靠人眼再核对一遍。本质上是拿时间换可靠性。


说话人2: 笑归笑,我现在最好奇的是:它到底有多慢?


说话人1: 来,全片最欢乐的部分。实测熟练工的峰值转录速度,大约是每秒1个字节。注意,是1个字节,不是1KB不是1MB,是1个字节。


说话人2: 每秒一个字节……我念出声都比这快吧。


说话人1: 算笔账你感受下。实验跑在Apple Silicon架构的机器上,那边Linux默认页面大小是16384字节,也就是16KB。读一整页要多久?单页读取时间等于页面大小除以传输速率,16384除以1,16384秒,合4.55个小时。


说话人2: 我喝咖啡等它读一页?咖啡凉透了都读不完,我得上一天班回来看它读完。


说话人1: 就算换x86的4KB小页面,4096秒,也得68分钟。作为对比,现代DDR内存带宽是每秒几十GB,咱保守按25GB算,25乘以10的9次方字节每秒,对上纸的1字节每秒——差了250亿倍。所以李博士给它起了个外号叫"DDR-32",意思是这性能相当于内存标准往回倒退了三十二代。


说话人2: 别人超频,它超退是吧。


说话人1: 但是啊,注意这个但是——慢成这样,它在功能上居然是个完整的内存:能读、能写、能持久保持。这就逼出一个特别本质的问题:内存,到底是什么?


说话人2: 是什么?


说话人1: 李博士整理的内容里有个特别漂亮的对应。图灵在1936年提出的图灵机,就三样东西:有限状态控制器、读写头、一条无限长的存储纸带。你再看这套纸质系统:CPU加操作系统,是控制器;缺页程序加上人工抄写,是读写头;那张写满十六进制的纸,就是纸带。三件套齐活,一台图灵机。


说话人2: 我的天,等于把1936年的理论模型,用今天的虚拟内存机制亲手在纸上搭了一遍。


说话人1: 对。所以最后,李坚毅博士有一段感悟,我原样念出来,觉得说得特别好——


说话人1: "存储的本质是信息的可寻址读写,与介质的具体物质形态无关。纸张、磁带、硬盘、内存,速度、密度、可靠性千差万别,但在计算模型的层面上,它们是等价的。"


说话人2: 这段话是真有味道。说白了,内存不是某一种电子零件,它是一个"位置"——一个你能按地址找到、能读、能写的位置。至于这位置是硅片上的小电容,还是纸上的一行字,计算理论根本不挑。


说话人1: 好,这期由李坚毅博士整理创作的话题就聊到这儿。下次你电脑再弹"内存不足",至少你心里有底了——理论上,手边有纸有笔,你就永远有内存。


说话人2: 就是读一页得抄四个半小时而已。


说话人1: 下期见。