Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

マルチGPUで探索中にクラッシュする #10

Closed
qhapaq-49 opened this issue Mar 29, 2020 · 10 comments
Closed

マルチGPUで探索中にクラッシュする #10

qhapaq-49 opened this issue Mar 29, 2020 · 10 comments

Comments

@qhapaq-49
Copy link

マルチGPUで対局が行えない

wcsc29の条件を再現しようとしましたが、マルチGPUを利用しようとすると対局中にクラッシュしてしまいます。以下に実験条件を記載します。もし原因に心当たりありましたらアドバイスをいただけると幸いです。

対局の途中、かつ再現性無くクラッシュします。エンジンを再起動し、クラッシュした局面をもう一度読ませても無事に読めてしまいます。頻度としては1対局に1度ぐらい(まともに対局を終了できない程度)です。

落ちた局面の一例

position startpos moves 2g2f 3c3d 7g7f 8c8d 2f2e 8d8e 6i7h 4a3b 2e2d 2c2d 2h2d 8e8f 8g8f 8b8f 2d3d 2b3c 5i5h 5a5b 3g3f 8f7f 8h7g P*2f 3i3h 3c7g+ 8i7g B*5e P*2b 2a3c 2b2a+ 3a4b 3d8d P*8b P*7b 7a7b P*2c 3c4e 8d8b+ 5e7g+ 7h7g 7f7g+ B*6h 7g7f P*7g 7f3f 2c2b+ 3b3c 2a3a G*9b 8b8e 2f2g+ 3h2g 3f2g 2b3b S*3h

用いたGPU

V100 2台

対戦環境

やねうら王と1手2秒対局。ponderなし。定跡なし。dlshogi側は一定時間対局モード。

enum SEARCH_MODE mode = SEARCH_MODE::CONST_TIME_MODE;
constexpr double CONST_TIME = 2.0;

usiの設定

wcsc29で配布していたものを使用。コードはdlshogiのmasterにある最新のものを使用。

setoption name DNN_Model value /home/swd/resnet/model_rl_val_fused_wideresnet10_selfplay_179
setoption name UCT_Threads1 value 2
setoption name UCT_Threads2 value 2
setoption name Byoyomi_Margin value 0
setoption name DNN_Batch_Size value 64
setoption name Softmax_Temperature value 166
setoption name C_init value 149
setoption name C_base value 39470
setoption name C_fpu value 20
setoption name UCT_Hash value 8388608

OS, cudaのバージョン, cudnnのバージョン

FROM nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04を元に構成。OSはUbunutu18、cudnnのバージョンは7、cudaは10.1

nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2019 NVIDIA Corporation
Built on Sun_Jul_28_19:07:16_PDT_2019
Cuda compilation tools, release 10.1, V10.1.243

dpkg -l | grep "cudnn"
hi  libcudnn7      7.6.3.30-1+c amd64        cuDNN runtime libraries
ii  libcudnn7-dev  7.6.3.30-1+c amd64        cuDNN development libraries and h

その他試したこと

  • FP16をon/offにしても何れのケースでもクラッシュします

  • UCT_Threadsを1や2や4に変えても何れのケースでもクラッシュします。

  • クラッシュする前から、2秒固定モードであるにもかかわらず、1手指すのに2秒以上かかるという予兆があることがあるようです(いきなりクラッシュすることもあるし、1手4秒とかかかるようになってからクラッシュすることもある)

  • nn->foward (forwardのtypo?)が遅くなっているようです。具体的にはUctSearch.cppnn_foward

      void nn_foward(const int batch_size, features1_t* x1, features2_t* x2, DType* y1, DType* y2) {
              double wstart = GetSpendTime(begin_time);
              mutex_gpu.lock();
              if(printall){
                double diff = GetSpendTime(begin_time)-wstart;
                if(diff > 0.1){
                  cout<<"info string lock wait gpu index "<<diff<<endl;
                }
              }
              wstart = GetSpendTime(begin_time);
              nn->foward(batch_size, x1, x2, y1, y2);
              if(printall){
                double diff = GetSpendTime(begin_time)-wstart;
                if(diff > 0.1){
                  cout<<"info string too slow calc gpu "<<diff<<endl;
                }
              }
    
              mutex_gpu.unlock();
      }
    

のように書き換えると

info string too slow calc gpu 0.222
info string lock wait gpu index 0.219
... 中略
// 一度遅くなり始めるとどんどん遅くなる。そしてある程度するとクラッシュする
info string too slow calc gpu 4.026
info string lock wait gpu index 4.004

のような出力が得られます。クラッシュする予兆が出る前はこのような出力はでてこないこと、too slow calc gpuが先にでてくることが特徴です。

@qhapaq-49
Copy link
Author

qhapaq-49 commented Mar 29, 2020

[update 20/03/10 11:40]

追記:シングルGPU、シングルスレッドでも落ちる

setoption name DNN_Model value /home/swd/resnet/model_rl_val_fused_wideresnet10_selfplay_179
setoption name UCT_Threads1 value 1
setoption name UCT_Threads2 value 0
setoption name Byoyomi_Margin value 0
setoption name DNN_Batch_Size value 64
setoption name Softmax_Temperature value 166
setoption name C_init value 149
setoption name C_base value 39470
setoption name C_fpu value 20
setoption name UCT_Hash value 8388608

でも落ちます。やはり落ちる前に

info string too slow calc gpu 0.813
info string lock wait gpu index 0.813
info string too slow calc gpu 1.059

と言ったログが吐かれます。私の理解が正しければ、1GPU、1スレッドでmutexのlockが意味をなすことはないと思ってたのですが、lockの解除待ちに時間がかかってる原因はわからないです(makefileはデフォルトを使ってるので最適化の過程で変なことをしてるとか?)

追記2 cudaのバージョンを10.0にしても落ちる

FROM nvidia/cuda:10.0-cudnn7-devel-ubuntu18.04 を用いてcudaのバージョンを10.0に合わせても落ちます。

$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Sat_Aug_25_21:08:01_CDT_2018
Cuda compilation tools, release 10.0, V10.0.130
$ dpkg -l | grep "cudnn"
hi  libcudnn7                     7.6.5.32-1+cuda10.0               amd64        cuDNN runtime libraries
ii  libcudnn7-dev                 7.6.5.32-1+cuda10.0               amd64        cuDNN development libraries and headers

追記3

CPUは32コアを使っています。体感的にCPUのコア数を落とすとクラッシュの頻度が落ちる気がします。

追記4 ubuntu16 + cuda10.1 + cudnn7.6でも落ちる

FROM nvidia/cuda:10.1-cudnn7-devel-ubuntu16.04 を元に構成しても落ちるようです。


$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2019 NVIDIA Corporation
Built on Sun_Jul_28_19:07:16_PDT_2019
Cuda compilation tools, release 10.1, V10.1.243
$ dpkg -l | grep "cudnn"
hi  libcudnn7                        7.6.3.30-1+cuda10.1   amd64                 cuDNN runtime libraries
ii  libcudnn7-dev                    7.6.3.30-1+cuda10.1   amd64                 cuDNN development libraries and headers
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="16.04.6 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.6 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

todo

  • cuda10.0+cudnn7.5はnvidiaが提供しているdocker-imageには無かったので、別途用意する必要があります(現在調査中)。
  • g++のバージョン依存性? (ubuntu16ではg++ 5.4.0がubuntu18ではg++ 7.4.0が使われてる模様)
  • wcsc29時点でのコードを使ってコンパイル+実行してみる release以下のソースコードはnn.cppが無い、atomic<bool>がコンパイルに弾かれるなどしてそもそもコンパイルできない
  • OS依存性...? (ubuntuでは動かない? READMEにubuntu16.0+cuda10.1+cudnn7.6の組み合わせが書かれているからそれを試す?)

@TadaoYamaoka
Copy link
Owner

以下のような手順でUbuntuでマルチGPUで動作できています。GPUはTesla V100です。

適当な作業ディレクトリで
nvidia-docker run -v $(pwd):/workspace -it pytorch/pytorch:1.3-cuda10.1-cudnn7-devel
※nvidia-dockerはdeprecatedなのでdockerが最新の場合はdockerコマンド

git clone https://github.com/TadaoYamaoka/DeepLearningShogi.git
cd DeepLearningShogi/usi/

viインストール
apt update
※upgradeするとバージョンが変わって実行できなくなるため実行しない
apt install vim

vi Makefile
CFLAGSに -DFP16 を追加

make

cd bin/
ls -l
usiができていること

apt install wget

wget https://github.com/TadaoYamaoka/DeepLearningShogi/releases/download/wcsc29/dlshogi-wcsc29.zip

apt install unzip

unzip dlshogi-wcsc29.zip

./usi
setoption name Byoyomi_Margin value 0
setoption name DNN_Model value /workspace/DeepLearningShogi/usi/bin/model_rl_val_fused_wideresnet10_selfplay_179
setoption name UCT_Threads value 2
setoption name UCT_Threads2 value 2
isready
※UCT_ThreadsXは使用するGPUのIDに合わせて設定する
※UCT_Hashは思考時間が2秒であればデフォルトでよい

position startpos
go btime 0 wtime 0 byoyomi 2000

将棋所などのGUIソフトから実行する場合は、以下のようにbatファイルを作成する。
@echo off
ssh user@hostname "docker exec -i containerid /workspace/DeepLearningShogi/usi/bin/usi"

@qhapaq-49
Copy link
Author

ありがとうございます。頂いた条件で動くことを確認しました。加えてSEARCH_MODE::CONST_TIME_MODEでも動くことを確認しました。

今まで動かなかった原因を検証したところ

setoption name UCT_Hash value 8388608

が悪さをしていたようです。一応2^nに属している(ZobristHash.cppにも怒られてない)のですが、ハッシュ計算の際に何らかのミスが生じているように見えます。2秒対局ぐらいならばハッシュサイズを大きくしなくても問題ないですが、大規模探索の際は欲を言えばもう少しハッシュを大きくしたい気がします。

@TadaoYamaoka
Copy link
Owner

8388608で遅くなるのは物理メモリが不足してスワップが発生しているためではないかと思います。
物理メモリが十分にあればデフォルトよりもある程度は大きくできるはずなので、とりあえず安定して動く範囲の大きさに設定してみてください。
私も大会のときは可能な限り大きめに設定していました。
メモリが不足しても落ちないようにはしたいので、落ちる原因は調べていますが今のところ再現できていません。

@qhapaq-49
Copy link
Author

ありがとうございます。内部構造への理解が足りていなくて恐縮ですが、dlshogiは対局中に追加で動的にメモリを取得するような作りになっているのでしょうか?
UCT_HashInitializeUctSearchで用いられて以降、使われている様子はなく、InitializeUctSearchの時点でUCT_Hash個分のuct_nodesmutex_nodesをnewしていたので、対局開始時にメモリが足りていれば対局中にメモリが不足することはないと思っていました。

また、その場合、メモリサイズに対してHashの値はどのようにして決めればよいでしょうか?

@TadaoYamaoka
Copy link
Owner

動的に変更はしていませんが、C++のnewは仮想メモリから確保するため、物理メモリ以上のサイズの場合、ハッシュが埋まるとページアウトが発生します。
サイズは、sizeof(uct_node_t)=11884byte × UCT_Hash でだいたいの量が計算できます。
このサイズが物理メモリに十分に収まるようにすれば大丈夫だと思います。

@qhapaq-49
Copy link
Author

うっ、不勉強で申し訳ありませんでした。色々騒ぎ立てましたが、つまるところ

  • ハッシュサイズが物理メモリに対して十分でないときに変な挙動をする
  • 物理メモリが偶々マルチGPUにしたときにおきやすい程度の大きさになっていた

ということだったのだと思われます。お手数をおかけしたお詫び and せめてものお礼として、ここまでのやり取りを纏めたdlshogi動かすマニュアルを作るので、良ければお使いいただければ幸いです(今晩辺りに完成させる予定です)。

@TadaoYamaoka
Copy link
Owner

ハッシュ以外の原因でクラッシュするマルチGPUで顕在化するバグがありましたので、修正しました。
commit 70407e9

@qhapaq-49
Copy link
Author

ありがとうございます。今更ながら動かし方を纏めたwikiページ(の雛形的なもの)を作ってみました。今までdlshogiをユーザ目線で動かしてきた経験を元に書いています。間違いや追加のリクエストがございましたらよろしくお願いします。

@TadaoYamaoka
Copy link
Owner

ありがとうございます!🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants