禁用 NUC 的快速启动

Intel NUC 有一个 BIOS 设置,叫快速启动(Fast Boot),我一开始不知道是什么东西,想想“快速”那就快速呗,于是就勾上了。之后就发现,再也进不了 BIOS 设置了。

于是我就知道了,这个“快速启动”,就是指开始的时候跳过 BIOS 选项界面,直接进入系统。而如果想再次进入 BIOS 呢,就要先把“快速启动”禁用掉,然后再开机按 F2。

关闭“快速启动”的步骤在 Intel 官网有写,大致是这样的:

  1. 先完全关闭机器,不能是休眠之类的;
  2. 开机的时候按住开机键不放,直到听到三声“哔”的声音,然后放掉开机键;
  3. 这时“快速启动”已关闭,可以按 F2 进入 BIOS。

我一共听了十次共 30 声“哔”…………

然后继续搜了一些其它资料,一位 Intel 员工在一个贴子里透露了一种暴力的方法:

  1. 先关机;
  2. 按下开机键,电源灯亮了之后,直接拔电源;
  3. 然后把电源插回去,开机,就可以按 F2 进 BIOS 了。

好吧,Intel 你赢了。

第六代 Intel NUC 安装体验

两年前购入了第一台 Intel NUC,一种迷你型的台式机,作为家庭娱乐用途。当初只考虑到看本地影片的需求,而没想到网络视频。这台机器可以勉强播放本地的 1080p 视频,但加上了网络传输之后就力不从心了,主要表现在它只能要么下载视频,要么播放视频,于是每看个几分钟就需要停下来等缓冲,体验很不好。

于是我又买了一台新的,NUC6i5SYK。这台机器带了最新一代的 Core i5-6260U CPU,性能肯定富裕了。

具体的配置如下。基本上算是一步到位,可以看很多很多年的视频了。

  • Intel® NUC6i5SYK
  • Kingston Technology HyperX Impact 8G * 2
  • Samsung 950 PRO 256G

硬件的安装很简单,就不详细说明了。底板拆下来之后就可以看到内存和硬盘的插槽,有防呆设计只有一种安装方式,不会搞错。如下图,上面是 M2 硬盘槽,底部是两条内存槽。

硬件组装完毕之后,开始装软件。和上次一样,继续装 Windows。可以在微软官网下载到 ISO 文件,解压到一个可以启动的 U 盘中就可以准备安装了。在安装之前,还需要准备另外一个 U 盘。

使用另一个 U 盘的原因,通俗一点来说,是这一届的开发人员不行 -_-。根据 BIOS 的版本不同,这个 NUC 有一定机率认不出 M2 接口上的设备,也就是硬盘。在安装系统之前升级到最新的 BIOS,需要把新的 BIOS 文件复制到 U 盘上,然后使用 U 盘启动。我一开始也以为这是一个简单的文件复制操作,但实际上并不然。开机按 F7 进入 BIOS 升级模式之后,NUC 会把 U 盘的引导信息覆盖掉,然后重启再进行 BIOS 升级,于是之前制作 Windows 启动工具就没有用了。

当然你可以先升级 BIOS,再用同一个 U 盘制作 Windows 启动盘。如果资源足够丰富,用两个 U 盘可以加快安装速度。

另外,Windows 10 还有一个小小的问题,它认不出这个 NUC 的无线网卡。如果打算装完系统直接使用无线网络的话,U 盘里还需要备一个网卡驱动程序。网卡驱动和 BIOS 文件都可以在 Intel 官网下载到,这里就不详述了。

把上面提到的东西都准备好之后,安装 Windows 还是很方便的,而且 SSD 速度非常快,大概 10 分钟就可以看到桌面了。

具体的评测过段时间再发。

如何战胜 AlphaGo?

李世乭今日再输一场,比分 0:3 负于 AlphaGo,与百万奖金无缘了。而 AlphaGo 今天的表现异常完美,开局 45 分钟左右,李世乭已经招架不住。赛后英文解说 Michael Redmond 更是直言,AlphaGo 很有可能成为继吴清源之后又一位开创新格局的历史性角色。

虽然我不懂围棋,但可以从计算机的角度来介绍一下 AlphaGo 有哪些弱点。看了一些赛后评论,发现多数都是从围棋的角度来讲棋,而忽视了计算机的东西。所谓“知己知彼”,了解 AlphaGo 是怎么工作的,才更有可能击败它。

先说说 AlphaGo 的工作原理。已经有一些文章详细地介绍过了,这里就简单说一下。AlphaGo 决策的时候有两个步骤,一是选出下一步棋所有可能的位置(由 Policy Network 做出),二是在这些可能的位置里,精算一个最优的(由 Value Network 做出)。新闻中提到的 AlphaGo 每天几千万盘棋,都是在训练 Policy Network,就是培养它尽可能找全所有价值高的点。而 Value Network 似乎是在比赛中实时计算的,不需要训练。

Value Network 的工作原理和自然人无异,就是一步一步推演,看看之后几步的胜负情况。这一步骤在讲棋的时候经常用到,嘉宾和主持人都会用棋子摆一摆,并揣测棋手下一步的动向。Value Network 也是这样做的,只是它算得特别快而已。我看了一些现场解说,一般都是算出之后的五到十步棋左右,越到后面,计算的复杂度越高。这对人和电脑都是一样的。

影响 Value Network 精确程度的一个重要因素是时间,比如给它五秒钟,它可以算到五步之后,给它十秒钟,它可以算七步。我重看了一下前两场比赛,刚开场的时候,AlphaGo 大约是每 60 - 80 秒下一步棋;而到了中盘的时候,决策时间会上升到两分钟以上。这是因为刚开场的时候,每个位置的重要性都差不多,算了几步之后发现各个位置都不错,就随便选一个即可。而到了中盘,一个位置可能要算上几十步才能确定它的重要性,于是耗时就上去了。

想要打击 AlphaGo,就必须尽量不给它时间做计算。让它计算的步数减小,提高犯错的可能性。要做到这一点,只有一个办法,增加 Policy Network 选出来的位置的数量。假设一个位置它要算 10 秒钟,那么 10 个并列的位置,它就要算 100 秒,这样就大大地增加了时间上的消耗。时间耗尽之后进行读秒阶段,这个阶段中,AlphaGo 大约 30 秒左右就会给出计算结果,估计是在程序中强制设定了的。很明显,30 秒和 2 分钟的计算相比,30 秒算得不清楚,更容易犯错。李世乭在第二场成功地把 AlphaGo 拖进了读秒阶段,但依然没有把握住,有点可惜。当然主要原因是当时李世乭自己也开始读秒了。

由于 AlphaGo 并不会在局部战场鏖战很久,即它没有局部战场的概念,每次选位置都会从整个盘面入手。虽然这样有很好的大局观,但也损失了不少计算性能。如果李世乭能够尽可能多地制造出重要性差不多的位置,可以极大地增加 AlphaGo 的计算量。而 AlphaGo 的应对方式,要么是增加计算时间,要么是在没算完的时候直接给出一个临时最优解,无论哪种方式,都对李世乭有利。

另外网络上有人提到下模仿棋。虽然模仿棋在围棋界不是什么光彩的事情,但对 AlphaGo 确实有效。所谓的模仿棋就是利用棋盘的对称性,对方在哪里落子,自己就在对称地方落子。对人类而言,模仿棋是有破解招数的(详情略);而 AlphaGo 是否有理解对方在下模仿棋,这一点还不清楚,需要我们的“高级软件测试工程师”来验证一下(笑)。如果 AlphaGo 没有对应模仿棋的特殊策略,按正常情况来选位置,那会相当于自己左右互搏,实际上也会产生一盘不错的棋。

模仿棋还有另一个好处,就是李世乭所消耗的时间不多。在前期节约一些时间,就可以把更多的时间放在中盘拉锯上,就更有可能获得胜利。由田渊栋的赛后分析来看,第一局中盘李世乭曾经一度扳了回来。所以有更多的时间放在中盘,李世乭更有希望赢得比赛。

无论如何,这场比赛都会被载入史册。虽然已经连输三场,还希望李世乭可以放下包袱,贡献出两场更为精彩的对局。

两年胜过一百年

AlphaGo 在昨天和今天两场比赛中以较大优势战胜李世乭,基本已经宣告了现代围棋百年基业的崩塌。围棋会成为国际象棋之后,另一个人类被计算机程序完全战胜的棋类项目。在战胜了棋类中最复杂的围棋之后,计算机算法也将统治所有的棋类游戏。

现代围棋从二十世纪初在日本兴起,由吴清源等宗师级人物开创,发展到现在已有一百多年,经历了数个时代。而 AlphaGo 从投入使用到战胜李世乭不超过两年。有消息说在 2014 年 4 月 AlphaGo 在弈城对战平台上注册了帐号用于实战练习,起始等级为业余五段。短短两年之内,实力从业余五段上升到可以和顶尖职业选手叫板,这样快速的进步令众多职业选手汗颜。

我对围棋没有那么了解,不过我可以从计算机的角度来讲解一下大家对 AlphaGo 的一些误区。

假设李世乭五番棋不敌 AlphaGo,中国的职业高手能否和 AlphaGo 一战?

如果计算机程序两年时间可以做到人类一百年才能达到的水平,那么全面超越人类也就是几个月的事情。1997 年深蓝在国际象棋上战胜世界冠军,到 2006 年人类最后一次战胜计算机,程序用了十年的时间赢下了国际象棋。而这一次,或许 AlphaGo 会用更短的时候全面超越人类。人类高手想要挑战 AlphaGo 还得趁早。

为什么 AlphaGo 依然会下出一些“臭棋”?

据 DeepMind 的开发人员表示,在第一盘棋中,AlphaGo 全程认为自己处于优势状态。当然程序可能有 bug,但更重要的一点是,人类认为某些下法不好,是真的不好么?人类下围棋,一天不过一两盘,顶尖高手两三天才能下一盘棋。以这种速度,在一两百年之内积攒出了各种理论、定式。而 AlphaGo 一天则可以自己和自己对战上千盘棋,对于一些围棋理论,显然 AlphaGo 会有更全面的看法。这些臭棋经过仔细研究,说不定会被证明是一步好棋。

不用正常围棋的路数,是否能迷惑 AlphaGo?

在人与人对战时,如果对方下了一步看不懂的棋,选手肯定会猜测这是一步好棋,还是故意晃点我。而 AlphaGo 还不具备这种能力,对于无论是有意还是无意的落子,AlphaGo 都会以精确地计算来应对。换句话说,AlphaGo 不会轻敌。

天网是否已经来临?

如果 AlphaGo 故意输掉了一盘,那才是令人恐惧的。如果你对计算机行业不了解,可以去搜索一下“图灵测试”。能通过图灵测试的程序才具有“思维”的能力,而其它的程序都只是按照人类的指令运行而已。目前还没有可以通过图灵测试的计算机程序。

收官阶段李世乭是否会有优势?

众多场外评论说收官阶段的“打劫”会对计算机程序造成一定的影响。我猜这一说法的原因是之前多数程序都处理不好这一步骤。至于 AlphaGo 懂不懂“打劫”的要领,暂时还无人可知,所有公开的对战中,AlphaGo 都没有走到“打劫”这一步就已经赢了。

从计算机算法的角度来说,收官阶段的计算肯定比中盘来得简单。举个例子,玩过”数独“的朋友都知道,在一个数独局面中,如果局面是全空的,很简单,随便填数字即可;如果局面差不多都满了,只有少数几个空,那也很简单,按着规律填。数独最难的局面,就是半满的局面,每个空都有多种可能,也有很多限制,要推演出每一种可能,需要大量的时间。围棋也一样,最需要计算的是中盘阶段。过了中盘之后,每多下一个子,计算复杂度呈指数级下降,计算机会觉得轻松了很多。即使中盘战和,在收官阶段,计算机也会具有巨大的优势。这也是为什么 AlphaGo 的多数比赛在中盘过后就显示出不可逆转的优势。

Google 内部对这场比赛怎么看?

很明显众多码农都很兴奋,有人甚至要求 DeepMind 团队在比赛时内部直播 AlphaGo 的决策过程,以增加观赏性。不过这一要求被 DeepMind 拒绝了,大概是不想泄露任何可能影响比赛进程的信息。

站点启用 Certificate Transparency

之前一直都以为 Certificate Transparency 这个东东是给 EV 用的,没想到今天看了篇文章,说是个人站点也可以用。于是就去申请了一下。

先简单说说 SSL 证书的安全性。SSL 的机制是一个简单的信任链关系,浏览器并不能区分两个受信任的 CA 对同一域名签发的证书。比如本站的证书是由 DigiCert 签发的,如果另一个 CA 有意或无意也签发了一个对于 leonax.net 的证书,浏览器在访问网站的时候并不知道哪个证书是“真的”,哪个是“假的”。于是如果有两个网站,使用了不同 CA 签发的证书,且都说自己是 leonax.net,那么浏览器都会显示出“安全”的图标。现在 SSL 证书泛滥,部分 CA 为了降低证书申请的门槛,并没有做到严格的域名审核步骤,导致一些恶意分子有机可趁,伪造证书来骗取用户的信任。

简单来说 Certificate Transparency 是一个用于增强 SSL 证书安全性的东西,它可以确保 CA (Certification Authority) 不乱发证书。CT 的做法是通过一个第三方的验证机制,来判断证书的改动有没有出现异常。比如上述情况,会有两个 CA 同时向验证服务器提交信息,或是一个提交了,浏览器却收到了另一个的证书,这样便可以区分出“真假证书”了。

本站的证书是在 DigiCert 申请的。DigiCert 对 Certificate Transparency 的介绍可以看这里。实际上它废话了一堆,只是告诉你要去联系客服开启 CT 即可。于是我就去找了客服,十分钟搞定,当中还绕来绕去说了一些废话,可能是因为美国当地时间是夜里,客服不太清醒的缘故。不过事情也不复杂,很快客服就给我重新签发了证书。拿到新的证书之后,再上传到网站服务器即可。

开启了 CT 之后,在 Chrome 的网站信息中就可以看到类似上图的字样。说是网站已提供有效的 Certificate Transparency 数据。

由快播的庭审说说加密解密的问题

今天是“快播”涉黄案开庭的日子,新浪网直播了庭审全过程,过程中充满了各种欢乐。我们来说说其中的一个:

且不说这位审判员对于法律是多么地无知,用户的文件无论有没有加密都属于个人隐私,能问出这样的问题显然是对隐私保护没有一丁点的认识。

接下来我们从技术的角度来说说,为什么不能解密。

加密解密实际上是纯数学的东西。如果把一个需要加密的文件看成是一串数字,比如一个文件由一串数字序列(A0, A1, A2, ..., An)构成,这个序列可以被人阅读和理解。加密的过程就是把上述 A 序列转换为(B0, B1, B2, ..., Bn),这个 B 序列是完全杂乱无章,看不懂的内容。然后解密就是加密的逆过程,把 B 序列再翻译回 A 序列。这两个转换过程中都需要大量的计算,而计算机的产生使用大规模加密解密成为可能。

加密解密的一个典型应用场景是寄信。比如小张要写一封信给小红,为了防止信件在寄送过程中被别人看到内容,小张可以把信的内容先加密,然后收小红收到信之后再解密,即可确保寄送过程中没有人可以看懂信件的内容。

加密解密的一个重要工具是密钥。密钥的本质也是一串数字序列(C0, C1, C1, ..., Cn),把它和 A 序列以某种方式混合,即可产生 B 序列。然后再把 C 序列和 B 序列以某种方式混合,即可产生 A 序列。这种方式称为对称密钥加密。常见的对称密钥加密方式是 AES,暴力破解 AES 加密需要千百万年的计算时间,因此被认为是安全的。

使用对称密钥加密的前提条件是,传递信息的双方事先要约定一个密钥,有了统一的密钥,才能顺利地加密和解密。我们在谍战剧里经常看到的,战争的一方截获对另一方的密码本,从而监听到了重要的信息。这个密码本,就是这里说的密钥。密钥需要定期更新,否则就有可能被对方暴力破解,或是以其它的方式窃取。

从谍战剧中我们可以看到,对称密钥加密的主要缺点就是,交换密钥不方便。虽然后续的通信都加密了,但是密钥的传输过程中却是公开的。密钥的传输过程成了加密解密中的薄弱环节。

那么有没有办法解决这个问题呢?当然是有的。这种方法称为非对称密钥加密

非对称密钥加密的密钥包含两部分:公钥和私钥,公钥可以公开,私钥需要保密。而非对称密钥加密是一个外人看来很玄乎的东西。先说说它的过程:小张手里有一对公钥 P 和私钥 X,小红手里有一对公钥 Q 和私钥 Y。小红先把自己的公钥 Q 告诉小张。小张使用 Q 和自己的私钥 X 把信件的内容 A 加密成 B,然后把 B 和小张自己的公钥 P 一起告诉小红。然后小红使用自己的私钥 Y 和小张的公钥 P 对加密内容 B 进行解密,即可还原出 A 来。相信看到这里多数人都已经晕了。

具体原理这是不多说,它和素数分解有关。它对于密钥的保护措施是加密的双方只需要交换公钥即可进行加密和解密,而即使公钥被第三个人知道,他也没有办法破解加密过的文本。常见的非对称密钥加密方式是 RSA,暴力破解 RSA 同样也需要千百万年。非对称密钥加密最常见的应用是 HTTPS。这下知道为什么 HTTPS 是安全的了吧。

于是这里就解答了那位审判员的疑惑,为什么不能对用户上传的文件进行解密,因为根本解不开。如果快播的用户在上传视频时使用了非对称加密,下载视频的用户在观看时解密,这个过程中快播是没有办法知道其中的内容的。聊天软件 Telegram 也使用了类似的方式进行端到端的加密,使用聊天内容就连 Telegram 自己也不知道。

和加密相关的另一个技术称为哈希(Hashing),哈希的作用是验证源文本的真实性。举个例子,小张立了一份遗嘱,他显然不需要对这份遗嘱加密,因为遗嘱最终是要公开的。而他要做的是,确保最终公布的那份遗嘱和他最初立下的是一样的。于是小张可以在立下遗嘱的时候对这份遗嘱做一个哈希,在遗嘱公开的时候,对公开的遗嘱再做一次哈希,如果两份哈希码一致,才说明遗嘱没有被改动过。当然这其中还涉及到一些哈希保密的步骤,这里不细说了,大家知道这个意思就可以了。

哈希和加密解密的一个重要区别是,哈希生成的哈希值,是没有办法解密的,就是还原不回去,只能把 A 哈希成 B,不能再从 B 推导出 A。哈希在计算机领域的一个常见用途是保存密码。比如你在某个网站上注册了一个帐号,这个帐号包含用户名和密码。而网站的管理员不希望除了你之外的其它人看到这个密码,于是网站上所保存的内容只是密码的哈希值,而不是密码本身。在你每次登录网站的时候,网站都会对你输入的密码做一次哈希,如果哈希值和网站数据库中存放的一致,则表示你输入的密码正确。而即使有人偷取了网站所保存的哈希值,也没办法还原出密码来,也就不能登录你的帐号。

现在主流的哈希算法是 SHA-2。一个常见的应用场景是两步验证

好了,说了这么多加密解密相关的东西,回过头来说说快播。我没有用过快播的软件,也不太清楚快播对色情视频的打击做到了什么程度。但从技术的角度来看,P2P 的加密内容分享是无法被解密的,这也加速了全球日益高涨的恐怖威胁。全世界的政府都在要求商业公司提供用户的解密数据,与之相对的是数学领域的加密理论已经远远把监控和破解甩在了身后。我不认为任何公司需要对技术的进步负责,科技的进步是大势所趋,而需要改进的,是那些仍处于落后状态的事物。

Go 语言中奇怪的 if 语句

上篇文章提到过 Go 语言中带有强烈的设计者的主观想法,Go 的 if 语句就是其中一例

常见的 if 语句大约是这个样子的(C++):

这样有一个问题:变量 event 定义在了 if 语句的外面,也就是说,在 if 语句之后,也可以继续使用 event 变量;而如果后续的操作中不需要 event 变量了,它实际上就造成了命名空间的污染。这并不是一个严重的问题,多数情况下不会造成任何问题,而如果一定要解决的话,在 C++ 中可以在 event 的定义之外套一层大括号来限定它的作用域。虽然代码看上去有一些奇怪,但无伤大雅。比如这样:

但是 Go 的设计者不知是出于什么原因,非要从语法上解决这个问题。于是 Go 中的 if 语句可以写成这个样子:

对,你没有看错。虽然 event 是定义在了 if 中,但它在 else 中也是可以用的。也就是说,这种写法实际上是上述的 C++ 写法的语法糖。

并不清楚 Go 的设计者添加这个语法糖的目的是什么。它仅仅是为了解决变量的作用域问题而提出,却牺牲了代码的可读性。if 语句可能会变得过长而不易阅读;在后续重构的过程中,拆分 if 语句也会变得困难。为了解决一个小问题而增加一种有问题的语法,看上去有点得不尝失。