您的位置:首頁>正文

教程|如何利用Google Colab免費訓練星際爭霸II

本文介紹了如何在Google Colab中提供的機器學習項目,

如果你想開始使用免費的StarCraft II機器學習環境, 請先完善GPU硬體, 您可以看一下我的Google Colab筆記本:https://colab.research.google.com/drive/1AzCKV98UaQQz2aJIeGWlExcxBrpgKsIV

最近, 我和幾位朋友開始了星際爭霸II的機器學習專案。 我覺得快速訓練神經網路的能力對於研究者的成功是很重要的。 為了向全球的星際爭霸II研究者提供一個可複現, 高效, 並容易分享代碼的環境, 我想看看我們能否讓StrCraft II在Google Colab(Google提供免費GPU的機器學習環境)上運行起來。

然而, 在下載了StarCraft II, 並安裝完必需的庫之後, 你會面臨以下問題:

I0331 08:30:17.832181 139972195997568 sc_process.py:148] Connection attempt 0 (running: None)****** omitted reconnection attempts ******I0331 08:32:17.048350 139972195997568 sc_process.py:148] Connection attempt 119 (running: -11)I0331 08:32:18.050124 139972195997568 sc_process.py:180] Shutdown gracefully.I0331 08:32:18.050344 139972195997568 sc_process.py:166] Shutdown with return code: -11Failed to create the socket.I0331 08:32:18.056085 139972195997568 sc2_env.py:327] Environment Close

構建額外的Pylons也無法修復這個問題。

理解返回代碼

我所做的第一件事就是弄清楚返回代碼的含義。

讀了PySC2的源碼(https://github.com/deepmind/pysc2/blob/39f84b01d662eb58b3d95791f59208c210afd4e7/pysc2/lib/sc_process.py)之後, 我找到了設置返回代碼的程式碼片段:

@propertydef running(self):return self._proc.poll() if self._proc else False

poll()來自Python的subprocess模組, 深入挖掘後發現11就是導致StarCraft中斷的信號。

信號11就是臭名昭著的段錯誤, 這個信號給C語言程式設計者帶來了無窮無盡的噩夢。

為了確認, 我發現SC2是可執行的, 而且是自行執行的。

> !~/StarCraftII/Versions/Base59877/SC2_x64Segmentation Fault (Core Dumped)

在硬模式下調試

正常情況下, 我會啟動最喜歡的調試工具, 那本文就變成了如何使用GDB的過程。

不過, 我們是使用Google Colab來處理的, 我們唯一擁有的就是一個Jupyter Notebook網頁。 這意味著:

1.沒有調試器

沒有根特權

3.工具有限, 比如沒有strace

RIP調試

當你只有一個網頁的時候......

第一步就是在伺服器上嘗試不同版本的星際爭霸II, 暴雪公司提供了星際爭霸II的4.0.2,3.17和3.16.1三個版本。 不幸的是, 沒有一個能夠成功。

然後我決定在本地Linux機器上運行星際爭霸II, 這個環境我可以控制並在其中進行調試。 它還允許我測試我的假設。

第一個猜想:沒有找到需要的庫

我最初的猜測是, StarCraft II作為一個遊戲, 可能需要某些OpenGL函數和庫, 而這些並不包含在我所用的Google Colab環境中。

為了驗證這個猜想, 我在本地機器上運行星際爭霸II, 這次是有strace工具的, 這使得我可以跟蹤系統讓星際爭霸II做了什麼。 由於所有的庫都通過作業系統載入了, 這樣一來, 我就能夠跟蹤任何一個缺失的依賴項, 或者查看是否有什麼奇怪的事情發生。

完整的trace日誌參見:https://gist.github.com/FrozenXZeus/53a85f58856cb346b90313110ce89bcc, 下面展示了一小段:

execve("./SC2_x64", ["./SC2_x64"], 0x7fffc19e08b0 /* 49 vars */) = 0brk(NULL) = 0x95bd000access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3...... openat(AT_FDCWD, "/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3...... openat(AT_FDCWD, "/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3...... openat(AT_FDCWD, "/lib64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3...... openat(AT_FDCWD, "/lib64/libm.so.6", O_RDONLY|O_CLOEXEC) = 3... openat(AT_FDCWD, "/lib64/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3......openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3.......

看一下這個結果, 除了動態連結C / C ++庫之外, 星際爭霸II沒有做任何事情, 這否定了我的假設。

那為什麼會出現段錯誤呢?

因為同樣的程式在我的本地機器上運行的時候沒有崩潰, 這也否定了暴雪的代碼有問題的假設。

快速搜索如何調試段錯誤使我想起了Valgrind(http://valgrind.org/), 令我驚訝的是, 該工具竟然可以在Google Colab上使用。

Valgrind的一段輸出如下:

==354== Process terminating with default action of signal 11 (SIGSEGV): dumping core==354== Access not within mapped region at address 0x8==354== at 0x6B3DF0: ??? (in /content/StarCraftII/Versions/Base56787/SC2_x64)==354== by 0x65FF97: ??? (in /content/StarCraftII/Versions/Base56787/SC2_x64)==354== by 0x89CD5C6: MallocExtension::Initialize() (in /usr/lib/x86_64-linux-gnu/libtcmalloc.so.4.3.0)==354== by 0x89B7D29: ??? (in /usr/lib/x86_64-linux-gnu/libtcmalloc.so.4.3.0)==354== by 0x7B79AD9: call_init.part.0 (dl-init.c:72)==354== by 0x7B79BEA: call_init (dl-init.c:30)==354== by 0x7B79BEA: _dl_init (dl-init.c:120)==354== by 0x7B69ED9: ??? (in /lib/x86_64-linux-gnu/ld-2.26.so)==354== If you believe this happened as a result of a stack==354== overflow in your program's main thread (unlikely but==354== possible), you can try to increase the size of the==354== main thread stack using the --main-stacksize= flag.==354== The main thread stack size used in this run was 8388608.==354====354== HEAP SUMMARY:==354== in use at exit: 0 bytes in 0 blocks==354== total heap usage: 4 allocs, 4 frees, 72,710 bytes allocated==354====354== All heap blocks were freed -- no leaks are possible==354====354== For counts of detected and suppressed errors, rerun with: -v==354== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)Segmentation fault (core dumped)

那麼, 唯一一個可以識別的函數就是libtcmalloc.so.4.3.0中的MallocExtension :: Initialize()。

對於不瞭解TCMalloc的人而言, 它是穀歌的定制化記憶體分配器, 用於Google Chrome等產品中。

等等......

回到我追蹤星際爭霸II的時候, 我記得只看到C / C ++庫被載入了。 這似乎不正確, TCMalloc是從哪裡來的呢?

結果證明, 有一種方式能夠讓TCMalloc在沒有使用TCMalloc編譯的程式上強制執行。

通過在Linux上設置LD_PRELOAD環境變數, 你可以加TCMalloc共用庫到程式中, 強制讓程式使用TCMalloc。

它在Google Colab上會是什麼樣子呢......

解決方案

不幸的是, 設置LD_PRELOAD環境變數並不能傳播到環境的其他部分中。

通過執行以下命令:

!apt-get uninstall libtcmalloc*

我成功地卸載了TCMalloc, 然後儘管還有錯誤資訊, 但是StarCraft II已經開始運行了, StarCraft II機器學習專案的大門也隨之開啟了。

我已經在Google Colab上提出了這個bug(https://github.com/googlecolab/colabtools/issues/106), 因此我們以後不必為此大費周折了。

基於STARCRARFT II進行的機器學習項目。

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示