基于浏览器/JavaScript 的国际象棋引擎(Engine)已在主流的国际象棋对弈网站(如 chess.com 和 Lichess)中流行已久。虽然这些引擎被移植至 JavaScript 后的确使得引擎的使用率被推广到了前所未有的高度,性能却大打折扣。
以我的 MacBook Pro(14英寸,2021年,搭载 Apple M1 Pro)为例,使用 Lichess 分析工具(运行以 WebAssembly 编译而成的 JavaScript 版 Stockfish NNUE)的分析速度约为每秒四百万节点(~4MN/s),如下图所示。
使用 Homebrew 在本地安装 Stockfish:
1 | brew install stockfish |
运行 Stockfish Bench 工具进行性能测试:
1 | stockfish bench 16 16 18 |
结果为近每秒一千六百万节点(~16MN/s)。根据以上数据可得,Javascript 版 Stockfish 在我的 MacBook 上仅有原本的 1/4 性能。
1 | =========================== |
使用
显然,从性能和效率上考虑,浏览器端引擎并不是一个优秀的解决方案。因此,在可行的条件下,我们应当尽量避免使用基于浏览器/JavaScript 的分析引擎。有关如何在国际象棋软件(Chess GUI)中使用 Stockfish,请参考此部分 Stockfish 官方 Wiki 中的内容(英文)。
另外,Lichess 提供了在其网页版分析工具中通过设置 WebSocket 服务器引入外置引擎的功能(GitHub - lichess-org/external-engine),利用这一功能,我们可以很方便地利用 Lichess 网页客户端使用原生引擎。另外,在 Lichess 上完成的对局也都显然能够直接用于分析。有关此功能的部署和使用,请见下节:云计算。
云计算
要取得更快的分析速度,在某些情况下,使用云计算服务可能是个不错的选择。然而,需要注意的是,与许多云服务的用法不同,运行国际象棋引擎是一个极度依赖于计算资源的项目,在大部分环境下,Stockfish 的性能则几乎完全由 CPU 数量决定。因此,事实上,要取得可观的、比多数个人计算机更快的分析速度,我们需要选用计算能力较强(CPU 数量较多)的资源,而这也意味着较高额的账单。
好消息是,AWS EC2 的计费方式较为灵活,我们仅需为实际使用量付费。当 AWS EC2 实例停机后,则不再产生费用。若配置合理,仅有与其关联的附加服务会继续产生一部分小额费用。因此,只要仅在实际需要使用引擎进行分析时启动计算实例,并在结束时及时停机,账单额度便完全可控。另外,我认为我们的使用情景完全可以接受使用 Spot(抢占)实例,通过相关设定能够进一步优化成本。
以我所选用的 c6a.8xlarge(AMD EPYC 7R13, 32 vCPU, 64 GB RAM)为例,On-Demand(按量付费)的使用费用约为 USD 1.22/小时,若每天开机一小时,则每个月产生的账单额度约为 USD 37.23(数据来自 AWS 价格计算器)。
若我们选择请求 Spot 实例,根据该型号的历史竞价情况预估,应当能节省约 42% 左右成本,即 ~USD 0.71/小时。
根据我们的需求,有关 Spot 实例请求的最佳设定(位于 Advanced details)如下图所示。
安装
我建议从 Stockfish 最新代码进行编译安装,以下步骤以此为例,使用的操作系统为 Amazon Linux 2(RHEL/CentOS)。你也可以下载 Stockfish 官方发布版本的预构建二进制文件。
1 | sudo yum install -y git gcc gcc-c++ make |
在 EC2(c6a.8xlarge)上使用 Stockfish Bench 工具,得到了速度显著高于我的 MacBook 的结果(~51MN/s)。
1 | =========================== |
Lichess 外置引擎
为避免不必要的未使用开机时长所产生的费用,我对 lichess-org/external-engine 的代码做了简单修改:
1 | if engine.alive and engine.idle_time() > args.keep_alive: |
若指定 --idle-shutdown 参数,则脚本将在空闲指定时间(--keep-alive)后自动停机以停止计费。
要使用我修改后的 Lichess 外置引擎脚本,请从以下库克隆代码并安装依赖:
1 | git clone https://github.com/binaryshell/external-engine |
接下来,请在 Lichess 网站创建具备外置引擎读写权限的 API 访问 Token。
你可以直接通过以下指令直接运行 Lichess 外置引擎服务:
1 | python3 example-provider.py --name "AWS EC2" --token=lip_YOURTOKEN --engine /usr/bin/stockfish |
不过,我建议将其设定为系统服务以便使用,以及在开机后自动启动。
编辑 /etc/systemd/system/external-engine.service 文件并置入如下内容:
1 | [Unit] |
其中,参数中的 --max-hash 及 --max-threads 值应当按照实例的属性调整以获得最佳性能。
载入并启用服务:
1 | sudo systemctl daemon-reload |
此时,登入 Lichess 分析面板即可选择使用外置引擎。
And enjoy! :)
参考
我在搭建此服务的过程中参考了这篇文章:Running Stockfish in the Cloud | MattPlaysChess(英文)。
其中,作者列出了部分 AWS EC2 实例型号运行 Stockfish Bench 工具的结果(性能),并介绍了在支持 UCI 协议的棋局分析工具(如 ChessBase 等国际象棋数据库软件)中通过 SSH 连接远程服务器上的 Stockfish 的相关思路。