ELFGO 编译和测试

编译过程

下载代码

从https://github.com/pytorch/ELF 下载代码
在ELF的根目录下git submodule sync && git submodule update --init --recursive获取第三方代码

使用docker方式进行构建

为减少对本地系统的冲击,可以使用docker 方式构建。
先进入ELF的根目录。
在编译前,需要对Dockerfile做一些小调整。
在原来的conda install后新增如下一行
RUN conda install pytorch torchvision cudatoolkit=10.0 -c pytorch
然后使用如下命令进行构建 (为了下载提速,挂了代理)
sudo docker build --network host  --build-arg HTTP_PROXY=socks5://127.0.0.1:1080 --build-arg HTTPS_PROXY=socks5://127.0.0.1:1080 -t elf_go:vtrunk .

运行时问题解决

启动制作好的image,拷贝到host中,以便使用GPU

sudo docker images 查看刚刚构建出的镜像id
启动如下的示例命令启动image,然后将我们需要的内容拷贝到host上
1
2
sudo docker  run  -dit  --name elf_go  ${your_image_id}
sudo docker cp elf_go:/go-elf ${your_host_elf_dir}

准备host机的路径

由于docker构建时使用了root用户,构建出的binary依赖了一些根路径下的目录。有很多办法可以解决这类问题。
治本的方案是修改编译体系,去除这些对根目录的依赖,将一个用户可控制目录作为根目录(或者使用相对路径)。但是修改的工作量比较大。
规避的办法也有一些,使用patchelf可以修改一些搜索路径,也可以考虑使用fakeroot等技术重定向文件访问的路径。修改的工作量还是略大。
这里用最粗暴的方法,用mount bind来建立一个满足访问要求的映射路径。
先行建立所需的路径。
1
2
sudo mkdir -p /root/miniconda3
sudo mkdir /go-elf
进入到我们拷贝路径${your_host_elf_dir},使用如下命令完成映射
1
2
sudo mount -o bind ./miniconda3/ /root/miniconda3
sudo mount -o bind ./go-elf /go-elf

最后设置搜索路径

1
export PATH=$PATH:/root/miniconda3/bin

下载v2版本模型

主线elf版本只能使用v2版本的模型,Dockerfile中下载的v0版本无法使用。可从

https://dl.fbaipublicfiles.com/elfopengo/pretrained_models/pretrained-go-19x19-v2.bin 下载后,放入${your_host_elf_dir}/go-elf/ELF中。

适配python版本

elf构建时docker内使用的python版本可能和host中的不一致。需要修改/go-elf/ELF/scripts/elfgames/go/gtp.sh中的启动命令,确保使用(dockerfile构建时)conda中安装的python版本。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
majiang@majiang-All-Series:~/hd/opensource/ELF_GO/builded_env/go-elf/ELF/scripts/elfgames/go$ git diff gtp.sh 
diff --git a/scripts/elfgames/go/gtp.sh b/scripts/elfgames/go/gtp.sh
index 0ca7aba..3291ade 100755
--- a/scripts/elfgames/go/gtp.sh
+++ b/scripts/elfgames/go/gtp.sh
@@ -9,7 +9,7 @@
MODEL=$1
shift

-game=elfgames.go.game model=df_pred model_file=elfgames.go.df_model3 python3 df_console.py --mode online --keys_in_reply V rv \
+game=elfgames.go.game model=df_pred model_file=elfgames.go.df_model3 python3.7 df_console.py --mode online --keys_in_reply V rv \
--use_mcts --mcts_verbose_time --mcts_use_prior --mcts_persistent_tree --load $MODEL \
--server_addr localhost --port 1234 \
--replace_prefix resnet.module,resnet init_conv.module,init_conv \
如果出现python版本不匹配问题,可能出现一些莫名其妙的模块找不到错误,如下所示。
1
ModuleNotFoundError: No module named 'torch._C'
其原因是,python的动态库对python版本有依赖,参考https://github.com/pytorch/pytorch/issues/574。host机器的python3如果不是conda所用的python3.7就会出现找不到库问题。

启动elf自带的脚本

1
2
3
4
cd /go-elf/ELF/scripts
source devmode_set_pythonpath.sh
cd /go-elf/ELF/scripts/elfgames/go/
./gtp.sh ../../../pretrained-go-19x19-v2.bin --loglevel off --gpu 0 --num_block 20 --dim 256 --mcts_puct 1.50 --batchsize 256 --mcts_rollout_per_batch 16 --mcts_threads 2 --mcts_rollout_per_thread 8192 --resign_thres 0.05 --mcts_virtual_loss 1

解决代码问题

v.pin_memory()处的cuda out of memory问题

加了print (v)语句。go-elf/ELF/src_py/elf/utils_elf.py 44行
print (v)
if gpu is not None:
with torch.cuda.device(gpu):
v = v.pin_memory()
v.fill_(1)
似乎是偶发故障,后续没有再复现

启动后使用genmove B开始下棋,utils_elf.py 210出现了数据维度不匹配的问题

genmove B会有异常,经过检查可能是下面utils_elf.py 210出现了数据维度不匹配的问题,修改接口后解决。

1
2
#bk[:] = v.squeeze_()
bk[:] = v.squeeze()

错误现象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> /go-elf/ELF/src_py/elf/utils_elf.py(192)copy_from()
-> for k, v in this_src.items():
(Pdb) y
*** NameError: name 'y' is not defined
(Pdb) q
Traceback (most recent call last):
File "df_console.py", line 86, in <module>
main()
File "df_console.py", line 79, in main
GC.run()
File "/home/majiang/hd/opensource/ELF_GO/builded_env/go-elf/ELF/src_py/elf/utils_elf.py", line 436, in run
self._call(smem, *args, **kwargs)
File "/home/majiang/hd/opensource/ELF_GO/builded_env/go-elf/ELF/src_py/elf/utils_elf.py", line 404, in _call
keys_extra, keys_missing = sel_reply.copy_from(reply)
File "/home/majiang/hd/opensource/ELF_GO/builded_env/go-elf/ELF/src_py/elf/utils_elf.py", line 192, in copy_from
for k, v in this_src.items():
File "/home/majiang/hd/opensource/ELF_GO/builded_env/go-elf/ELF/src_py/elf/utils_elf.py", line 192, in copy_from
for k, v in this_src.items():
File "/home/majiang/hd/opensource/ELF_GO/builded_env/miniconda3/lib/python3.7/bdb.py", line 88, in trace_dispatch
return self.dispatch_line(frame)
File "/home/majiang/hd/opensource/ELF_GO/builded_env/miniconda3/lib/python3.7/bdb.py", line 113, in dispatch_line
if self.quitting: raise BdbQuit

GTP协议问题

gtp脚本启动后可以在文本界面下使用GTP协议的指令下棋了。
但是sabaki围棋前端界面无法正常与eflgo进行GTP通信。
查看GTP协议,是ELFGO的额外打印干扰了协议解析。
参考https://github.com/pytorch/ELF/compare/master...Narsil:master,调整了console_lib.py 中的

1
2
3
    def print_msg(self, ret, msg):
- print("\n%s %s\n\n" % (("=" if ret else "?"), msg))
+ print("%s %s\n\n" % (("=" if ret else "?"), msg))

启动gtp脚本时,可以添加–loglevel off选项关闭大量额外打印。

封装脚本

为了sabaki等前端能比较方便的启动ELFGO后端,可以使用如下的封装脚本一次完成启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
#set -x
cur_shell_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd ${cur_shell_dir}

cd ../../../../../
sudo mount -o bind ./miniconda3/ /root/miniconda3
sudo mount -o bind ./go-elf /go-elf
cd -

export PATH=$PATH:/root/miniconda3/bin
cd ../../
source devmode_set_pythonpath.sh
cd -
./gtp.sh ../../../pretrained-go-19x19-v2.bin --loglevel off --gpu 0 --num_block 20 --dim 256 --mcts_puct 1.50 --batchsize 256 --mcts_rollout_per_batch 16 --mcts_threads 2 --mcts_rollout_per_thread 8192 --resign_thres 0.05 --mcts_virtual_loss 1

遗留问题

在sabaki中,当前elfgo还是只能 执黑。如果执白还是会卡死,可能协议文本的输出还有问题。
另外,说明中提到elfgo只能走贴7.5目的规则。

另一个围棋AI,可以给出胜率估计的leela-zero

下载并解压Lizzie.0.7.2.Mac-Linux.zip,然后进入解压后的目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export http_proxy="socks5://127.0.0.1:1080"
export https_proxy="socks5://127.0.0.1:1080"
git clone https://github.com/gcp/leela-zero
cd leela-zero
git submodule update --init --recursive
sudo apt install libboost-dev libboost-program-options-dev libopenblas-dev opencl-headers ocl-icd-libopencl1 ocl-icd-opencl-dev zlib1g-dev
sudo apt install cmake g++ libboost-dev libboost-program-options-dev libboost-filesystem-dev opencl-headers ocl-icd-libopencl1 ocl-icd-opencl-dev zlib1g-dev
mkdir build
cmake ../
...
CMake Warning at CMakeLists.txt:129 (message):
Qt is not found, build for `autogtp` and `validation` is disabled
...
cmake --build .
cd ../../
cp ./leela-zero/build/leelaz ./
chmod +x ./lizzie.jar
./lizzie.jar