无X server服务器运行Unity ML-Agents与python mlagents API对接

濮阳俊明
2023-12-01

前言

  Unity ML-Agents1是一个类似于gym的一个3D强化学习仿真平台,你可以用它现成的环境来训练模型,也能通过其开发规范自己设计一个仿真环境用于训练。在使用它的时候,由于它不像gym一样有个方法可以自主选择是否渲染,而我在官方的资料中也没翻到如何设置为不渲染的模式,这样一来使用的时候必须显示图形化界面,而一些Linux服务器(尤其是那些只提供Jupyter Lab的服务器)可能并没有提供足够的权限来为之配置。当手中有一台服务器,却没法用它来跑东西是一件很难受的事。好在,遇上我这么一个爱折腾Linux的人说什么也得给它部署上去,于是探索的旅程从此开启。

可用工具

  • Xvfb: 一个轻量的虚拟X server。
  • chroot:root权限下用于设置一个目录为根目录,并在这个新的根目录下里面运行命令。
  • Proot2 : 一个无root权限可用的类chroot+mount工具。
  • ubuntu rootfs3: 一个小型的ubuntu根文件系统,利用chroot可实现类似于切换到一个新的系统中。

原理

  利用proot进入到ubuntu rootfs,利用rootfs里面的Xvfb搭建一个虚拟X server用于unity引擎显示画面,并且在里面运行ML-Agents环境。

尝试运行ML-Agents环境

  • 运行环境:一台只提供Jupyter Lab的64位服务器,无root权限,无X server和Xvfb。
  • 所用rootfs:ubuntu 16.04的rootfs
  • 测试ML-Agents:Roller Ball4

  接下来将按照如下步骤进行:

  1. 点击这里或使用百度网盘(提取码:sutd)下载rootfs压缩包,将rootfs压缩包上传到jupyter并解压到某个位置。
  2. 点击这里或使用百度网盘(提取码:x788)下载ML-Agents压缩包,上传ML-Agents文件并解压到rootfs下的某个位置,比如rootfs的根目录下,并根据自己的可执行文件的位置修改如下命令添加执行权限:
    chmod +x linux/rollerball.x86_64
  3. 下载静态编译版的proot 可执行文件,重命名为proot,上传到jupyter,同样利用chmod命令为proot添加执行权限:
    chmod +x proot
  4. 在jupyter新建一个终端,根据你的文件位置修改如下命令并执行启动Xvfb
    PROOT_NO_SECCOMP=1 ./proot -b /dev -b /proc -r ./ubuntu-rootfs/ Xvfb :1 -screen 0 800x800x16
    其中PROOT_NO_SECCOMP是proot支持的一个标识,由于我用的服务器用了seccomp(一种内核安全机制),因此设置了这个变量,没设置的情况下运行之后的proot命令会报错“proot info: pid 4349: terminated with signal 11”;proot的-b参数代表要挂载哪个目录到rootfs根目录下面,由于Unity运行时需要读取/proc和/dev下的文件,因此需要挂载这两个目录;-r参数代表rootfs的根目录所在目录;最后加上在rootfs下所需执行的命令Xvfb,其他可用参数详见这里。Xvfb的参数 :1 与DISPLAY环境变量含义一致,-screen后的第一个0代表第一个屏幕,800x800x16代表屏幕配置为800x800 16位深色彩。
  5. 自定义ML-Agents启动文件,具体操作为新建文件(如myrollerball.x86_64,文件名可任意,但后缀用于mlagents库识别,不能缺失),其中的路径根据自己实际情况作修改,文件内容如下

#!/bin/sh
export PROOT_NO_SECCOMP=1
export DISPLAY=:1
./proot -b /proc -b /dev -r ./ubuntu-rootfs/ /linux/rollerball.x86_64 $1 $2

其中, 环境变量DISPLAY对应上面的Xvfb参数 :1,用于设置GUI应用显示在哪个端口。$1和$2表示该脚本接收的第一个参数和第二个参数,由于mlagents库启动环境会传入两个参数 --mlagents-port端口号,因此需要同时将这两个参数也传到ML-Agents可执行文件。

  1. 使用python API对接ML-Agents,代码如下
from mlagents_envs.environment import UnityEnvironment

env_name = './myrollerball.x86_64'
env = UnityEnvironment(file_name=env_name, base_port=5004)
env.reset()

如无报错成功执行即为连接成功,最后记得使用env.close()关闭连接。


  1. https://github.com/Unity-Technologies/ml-agents ↩︎

  2. https://proot-me.github.io/ ↩︎

  3. https://uk.images.linuxcontainers.org/images/ ↩︎

  4. https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Learning-Environment-Create-New.md ↩︎

 类似资料: