本文介紹了如何在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 Falsepoll()來自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編譯的程式上強制執行。
它在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進行的機器學習項目。