这个学霸疑似巨额知识来源不明 - 第91章 让程序去找程序

上一章 目录 下一章
    第二天,他跑了全套测试。
    把新旧两套流程吐出来的几十gb结果进行比对。
    结果全部一致。
    再看最终成绩。
    旧流程跑完要五个多小时。
    换上他这个专门给五个数排序的小东西之后,省下二十一分钟。
    二十一分钟。
    放进一个五六小时的大任务里,这数字小得可怜,像从一桶水里舀走一勺。
    换个外行看,会觉得他熬了一整夜,就为这点东西,简直是捡了芝麻丟了西瓜。
    但江临不这样认为。
    因为这套工具不会只跑一次。
    这个项目后面还有几十组要重跑,这套工具以后还要接別的活儿。
    今天省二十一分钟,明天省二十一分钟,跑上一百次,省下的就是三十多个小时的高强度算力。
    这意味著,他能用更少的机器,跑出更快的叠代速度。
    更何况,这只是他揪出来的第一颗小石头。
    一个年久失修、堆满了懒惰和冗余的老系统里,这样的小石头,一定还有成百上千颗。
    他在记录的末尾这样总结。
    一件事被重复的次数足够多,最微小的效率差距,就会撕裂成生与死的鸿沟。
    在这个城市,代码写错了,大不了多扣几块钱伺服器费用,大不了半夜爬起来重启,大不了回滚重来。
    有售后,有同行,有无数冗余可以挥霍。
    但在那个他迟早要回去的废土世界里,没有云伺服器,没有售后,没有第二个工程师替他擦屁股。
    在那里,机器慢了,不能先要资源,必须先问。
    为什么慢。
    底层快一点,省一点,从来不是写进简歷的性能指標。
    而是活下去的余量。
    写下这句话,江临把这个给五个数排序的小东西,单独归到一个新建的文件夹里。
    然后,一个新的念头浮了上来。
    五个数,他靠纸笔和经验,一晚上能推出来。
    可如果是六个数、七个数、八个数呢?
    要排序的数字每多一个,可能的排法就成倍地,再成倍地往上翻,很快就会多到一张纸根本画不下。
    而且,比较次数最少不等於实际跑得最快。
    还要看机器喜不喜欢这套顺序,看那些岔路藏在哪里。
    到那时候,凭一个人的脑子去硬想哪一套手势最好,会越来越不靠谱。
    不是不能写。
    只是人会变成那个最慢的瓶颈。
    江临忽然想到一件事。
    如果给五个数排序的完美手势,是可以靠一台机器,把所有可能的排法挨个试一遍,自己找出来的。
    那別的小动作呢?
    那些同样被重复几千万次,同样卡著整个系统脖子的小动作呢?
    人来定规矩,定好什么算对,什么算错,什么是绝对不能碰的红线。
    然后,让程序自己去试,去试错,去在那片大得可怕的可能性里,替自己捞出那一段更小,更快,更稳定的代码。
    不再是人埋头一行行去写。
    是写一个程序,让这个程序,去寻找別的程序。
    好吧,让程序去找程序,听著挺玄,到底有什么用?
    打个最简单的比方。
    你家里有一把瑞士军刀,剪刀、开瓶器、螺丝刀、锯子,什么都有,出门带一把,啥都能应付一下。
    可如果你开了家工厂,流水线上每天只干一件事。
    拧同一种螺丝,一天拧几百万颗,你还会用军刀上那个小螺丝刀去拧吗?
    当然不会。
    你会专门定做一把电动螺丝枪,只为这一种螺丝量身打造,又快又稳。
    电脑也是一样。
    它平时用的那些现成功能,全是瑞士军刀。
    为了应付天下所有情况,做得万能,可靠,可每用一次都得把整套复杂东西开动一遍。
    但现实里很多任务,其实就是那条每天拧几百万颗同款螺丝的流水线。
    动作简单,规矩固定,就是次数多得嚇人。
    江临前一晚乾的,本质就是给这样一条流水线,亲手定做了一把专用的螺丝枪。
    而让程序去找程序,是把这件事再往前推了一步。
    定做螺丝枪本身也是累活儿,得懂材料,懂力道,反覆试。
    他不想每遇到一种新螺丝,就熬夜亲手去打一把新枪。
    他想要的,是一台会自己造螺丝枪的机器。
    你只管告诉它我要拧这种螺丝,必须拧紧,不能滑丝,剩下的,它自己去试一千种枪头,自己测哪种最快最稳,最后把那把最好的递给你。
    人只负责说清楚我要什么,什么绝对不能出错。
    造枪的活儿,交给机器。
    那这东西在生活里能干嘛?
    答案是,几乎所有动作不难,却要重复亿万次的地方,背后都藏著这样一条可以被改造的流水线。
    你滑手机相册,几千张照片唰一下按时间排好,是排序。
    你网购时商品按价格从低到高一列,是排序。
    地图给你算最近的路,外卖给你派最近的骑手,游戏里每一帧成百上千个物体重新排先后……
    这些你天天在用,却从不留意的瞬间,底层全是同一批被重复了千万上亿次的小动作。
    平时没人在乎它们快一点还是慢一点,因为单看一次,都是眨眼的事。
    可一旦放到重复上亿次的尺度上,这眨眼的差距,就会变成实打实的电费、伺服器和等待时间。
    江临要做的机器,就是钻进这些没人留意的角落,把那些还能更快的小动作,一个个揪出来,定做,替换,提速。
    而且它不挑活儿。
    今天能给五个数排序,明天就能优化別的小动作。
    这个项目用得上,下个项目照样用得上。
    一念及此,江临越来越兴奋。
    因为排序,只是个敲门砖。
    真正让他头皮发麻的,是这道门缝背后那个更大的东西。
    如果连找最优程序这件事本身,都能交给机器去做呢?
    那么在废土世界里,他就不必再为每一个装置,每一种控制顺序,每一套观测流程,都亲手去写最好的方案。
    他一个人,精力有限。
    但如果有一天,机器能替他搜出一部分小程序,小流程,小动作。
    那么它就不再只是一个排序工具,而是一个单人科研系统的增幅器。
    过去,人写程序,是亲手给出每一步。
    第一步比这两个数,第二步比那两个,第三步交换……
    一步步把答案铺出来。
    这要求写的人脑子里先有答案,再把答案翻译成代码。
    江临现在想做的,是反过来。
    他不再亲手给答案,只告诉机器三件事。
    什么是起点——一堆乱掉的数。
    允许做什么动作——挑两个位置,比一下,错了就换。
    什么算贏——所有可能的乱序,最后都被捋顺。
    然后,让机器自己去试。
    说白了,就是把排序这件事,变成了一个游戏。
    乱掉的数,是棋盘。
    每一次比一下,该换就换,是落子。
    把所有乱序都捋顺,是通关。
    机器要做的,就是自己去玩这个游戏,一步步试,直到找出一套能通关的走法。
    这个想法有个让人头皮发麻的地方。
    人,从此不必知道答案了。
    人只负责定义这个游戏。
    画好棋盘,定好规则,標好胜利的样子。
    至於具体怎么走,走哪条路最快,交给机器去穷举,去试错。
    江临新建了一个文件,敲下三行注释,作为这个游戏的全部规则。
    有一堆乱掉的数。
    每一步,挑两个位置比一下,错了就换。
    直到所有数都被捋顺。
    很短。
    短到不像一个程序的开始。
    但他盯著这三行看了將近一分钟。
    因为这三行的意思,已经不再是手写排序,而是让机器自己搜索排序程序。
    第一个要解决的问题是,机器怎么知道自己试对了?
    这恰恰是这条路最乾净的地方。
    五个数,所有可能的乱序,一共只有一百二十种。
    一百二十种,小到可以一种不漏地全列出来。
    所以机器根本不需要猜某套走法对不对。
    它可以把这一百二十种乱序全部丟进去,让那套走法挨个跑一遍,只要有一种没被捋顺,这套走法就当场判死,扔掉。
    这是数学意义上的乾净。
    不是我觉得它应该对,而是我把所有可能都试过了,它就是对的。
    人靠直觉,会漏,会错。
    机器靠穷举,一种都不会放过。
    凌晨,第一版找程序的程序跑了起来。
    它很笨,几乎不会偷懒,只是从所有该比哪两个的选择里,一层一层往下试。
    每走一步,就回头看看那一百二十种乱序,还剩多少没被捋顺。
    哪条路让混乱减少得最多,就顺著那条往下走。
    江临给它定了个朴素的评判標准。
    剩多少没排对,用了几次比较,有没有引入岔路,有没有破坏两个数相等时保持原顺序的规矩,有没有把缺失的数据提前隔离出去。
    没有什么玄乎的智能模型。
    只有最原始的三样东西:挨个试,及时砍掉死路,把所有可能都验一遍。
    这是他这台机器现在跑得动的全部。
    第一轮结果出来,屏幕上列印出一串走法。
    江临先验证。
    一百二十种乱序,全过。
    两个数相等的情况,过。
    缺失数据的隔离,过。
    然后才看速度。
    没比他自己手写的快多少,某个设定下甚至更慢。
    他反而长长鬆了口气。
    这才正常。
    第一版找程序的程序,怎么可能一出来就碾压一个人熬了一整夜的经验。
    但它已经证明了那件最重要的事。
    机器,可以自己找到正確的程序。
    快不快,是下一层的问题。
    能不能找到,才是这扇门开没开。
    接下来的时间里,江临一点点餵养这个还很笨的东西。
    第一个台阶,是让它分清对不对。
    这个最简单,穷举就行。
    五个数的一百二十种,八个数的几万种,机器都能一种不漏地验完。
    第二个台阶,是让它分清值不值。
    同样能把数排对,可能有十几套不同的走法,它们不是一样好的。
    有的比较次数多,有的岔路多,有的要占用更多临时空间。
    江临得把这些代价一项项写进机器的评判標准里,让它在一堆都对的走法里,挑出最划算的那个。
    第三个台阶,最麻烦。
    让它明白机器认不认。
    同样一套走法,写在纸上看著差不多,可一旦真的跑起来,换一台电脑,换一种翻译方式,快慢竟然会不一样。
    因为最终真正执行的,不是纸上那几行字,而是机器把它翻译成的更底层的一长串指令。
    一套看起来比较次数最少的走法,翻译到机器里,未必就是跑得最快的那个。
    到了这一层,纸笔和直觉彻底失效。
    人根本算不清,哪一套走法在真实的机器里会更快。
    而这,恰恰是让程序去找程序最大的价值所在。
    人算不清的事,机器可以一套一套地真跑,用秒表去量。
    它不需要理解为什么快,它只需要把成千上万套候选走法挨个跑一遍,然后告诉你。
    这一套,最快。
    但江临也很快撞上了这条路的天敌。
    爆炸。
    数字稍微多一点,可能的走法就成倍再成倍地往上翻。
    五个数还能全试,到了更大的规模,哪怕机器一刻不停地试到宇宙尽头,也试不完所有的路。
    这时候,砍就比试更重要了。
    江临想起之前解过的一道竞赛题。
    那道题的关键,不是把所有可能的答案都算一遍,而是先证明哪些答案根本不可能是最好的,然后整批整批地划掉,只在剩下的小范围里找。
    搜索也是一样。
    机器不可能走完所有的路,但它可以先证明,一大批路,从某一步开始就註定不可能更好了。
    於是这些路,连试都不必试,整批扔掉。
    把这件事干好,需要的不是更快的机器,而是更聪明的放弃。
    在每一个岔路口,提前算出往这边走,最好也只能到这个程度,一旦发现这个上限还不如手里已经有的答案,立刻掉头。
    省下的,是天文数字般的无用功。
    某个深夜,第一个真正有分量的结果,出现了。
    带著脏数据规矩的的五个数排序。
    允许有相等的数,允许有缺失的空洞,还要保证排完之后,相等的数维持原来的先后。
    机器找出来的那套走法,和江临亲手写的,不完全一样。
    比较次数一样多。
    但岔路更少,结构更规整。
    他把所有的脏情况一种种餵进去验。
    全过。
    再上秒表。
    比手写版快了百分之二点几。
    换一台机器,换一种翻译方式,领先的幅度变小了,但没有消失。
    百分之二点几。
    听起来甚至有点可怜,没有谁会为这个数字鼓掌。
    事实上,最后留在硬碟里的,也只是一个不起眼的小文件,旁边附著一份自动生成的验证报告。
    所有乱序通过,相等值通过,缺失值通过,与標准做法零差异,速度中位数快百分之二点七。
    就这么点东西。
    但江临心里清楚它和昨天那个手写版的本质区別。
    这一次,那套漂亮的走法,不是人写的。
    是机器自己,从茫茫的可能性里,捞出来的。
    標准库里的通用流程,被无数工程师打磨过很多年。
    而现在,它在一个特定的场景里,被比了下去。
    哪怕只是一点点,哪怕没人鼓掌。
    动手的,也不再是某个天才的脑子,而是一台肯把所有可能都试一遍的机器。
    他没有为这百分之二点几高兴多久,反而很快皱起眉。
    太小了。
    不是嫌弃这个结果,而是这个结果在告诉他一件事。
    方向是对的,方法还很粗。他给机器定的游戏规则太简单,让它放弃的本事太弱,能让它玩的盘面太小。
    机器现在像个刚学会规则,只会埋头硬试的新手。
    它能贏,但贏得笨拙。
    而江临已经看到了这条路真正的尽头在哪里。
    现在的机器,是按死规矩去试。
    但如果有一天,它能从自己过去试过的成千上万套走法里,回头去学。
    哪一类结构容易快,哪一类机器特別喜欢,哪一类看著比较次数少,跑起来却慢,那它就不再是埋头硬试的新手了。
    它会开始有直觉。
    人定义游戏,机器去玩,再从玩过的每一局里,长出自己的偏好。
    到那时候,让程序去找程序这件事,才算真正长出了牙齿。
    但江临没有立刻去碰那一步。
    现在还太早。
    他手里只有一个笨拙的找程序的程序,一个快了百分之二的小文件,几份测试报告。
    这不是成果,只是门缝。
    可很多最终会改变一切的东西,一开始,都弱得可笑。

添加书签

搜索的提交是按输入法界面上的确定/提交/前进键的
上一章 目录 下一章