$ gcloud functions logs read helloworld --region asia-east1
LEVEL NAME TIME_UTC LOG
I helloworld 2023-08-06 15:48:33.154 Default STARTUP TCP probe succeeded after 1 attempt for container "helloworld-1" on port 8080.
$ gcloud functions logs read helloworld --region asia-east1
LEVEL NAME TIME_UTC LOG
I helloworld 2023-08-06 15:50:14.490 Hello, World!
I helloworld 2023-08-06 15:50:14.395
I helloworld 2023-08-06 15:50:14.260
I helloworld 2023-08-06 15:48:33.154 Default STARTUP TCP probe succeeded after 1 attempt for container "helloworld-1" on port 8080.
$ python ts.py
INFO:__main__:match David vs Bob, winner: Bob
INFO:__main__:match Charlie vs Eve, winner: Charlie
INFO:__main__:match Alice vs Frank, winner: Alice
...(省略)...
INFO:__main__:winner Bob 31.327(0.95) ->31.351(0.95), loser David 22.064(0.89) ->22.043(0.89)
INFO:__main__:winner Alice 36.249(1.08) ->36.279(1.08), loser Charlie 26.857(0.90) ->26.835(0.90)
INFO:__main__:winner Eve 18.549(0.94) ->18.623(0.94), loser Frank 14.695(1.03) ->14.606(1.03)
INFO:__main__:player Alice 36.279(1.08)
INFO:__main__:player Bob 31.351(0.95)
INFO:__main__:player Charlie 26.835(0.90)
INFO:__main__:player David 22.043(0.89)
INFO:__main__:player Eve 18.623(0.94)
INFO:__main__:player Frank 14.606(1.03)
$ python elo.py
INFO:__main__:match David vs Bob, winner: Bob
INFO:__main__:match Charlie vs Eve, winner: Charlie
INFO:__main__:match Alice vs Frank, winner: Alice
...(省略)...
INFO:__main__:winner Bob 1808 ->1811(2), loser David 1357 ->1355(-2)
INFO:__main__:winner Alice 2062 ->2064(1), loser Charlie 1584 ->1583(-1)
INFO:__main__:winner Eve 1170 ->1179(9), loser Frank 1015 ->1005(-9)
INFO:__main__:player Alice 2064
INFO:__main__:player Bob 1811
INFO:__main__:player Charlie 1583
INFO:__main__:player David 1355
INFO:__main__:player Eve 1179
INFO:__main__:player Frank 1005
また、実行すると次のような折れ線グラフが得られる。
上記から、理論上のレーティングに収束するまで大体 200 ラウンドほど要していることが確認できる。
収束を早くしたい場合には、レーティングを計算する際の定数 K (サンプルコードの K_FACTOR) を大きくすれば良い。
しかし、大きくすると今度はレーティングの変化も大きくなるため値が安定しにくくなるというトレードオフがある。
このトレードオフを緩和するために、最初の頃の対戦では定数を大きくしておいて、その後は小さくしていくようなテクニックもあるようだ。
リリースの大きな目玉として CUDA を使った学習の実装が全面的に書き直されたことが挙げられる。
以前の LightGBM は、GPU を学習に使う場合でも、その計算リソースを利用できる範囲が限られていた。
それが、今回の全面的な刷新によって、利用の範囲が拡大されたとのこと。
ただし、PyPI で配布されている Linux 向け Wheel ファイルは CUDA での学習に対応していない。
対応しているのは CPU と、GPU でも OpenCL の API を使ったもの。
そのため、もし CUDA を使った学習を利用したい場合には自分で Wheel をビルドする必要がある。
$ python3 example.py
[LightGBM][Info] Number of positive: 3264308, number of negative: 2895691[LightGBM][Warning] Auto-choosing col-wise multi-threading, the overhead of testing was 0.252465 seconds.
You can set`force_col_wise=true` to remove the overhead.[LightGBM][Info] Total Bins 6132[LightGBM][Info] Number of data points in the train set: 6159999, number of used features: 28[LightGBM][Info][binary:BoostFromScore]: pavg=0.529920 ->initscore=0.119824[LightGBM][Info] Start training from score 0.119824[100] valid_0's auc: 0.811524[200] valid_0's auc: 0.819294[300] valid_0's auc: 0.822628[400] valid_0's auc: 0.825188[500] valid_0's auc: 0.827045[600] valid_0's auc: 0.828482[700] valid_0's auc: 0.829784[800] valid_0's auc: 0.831063[900] valid_0's auc: 0.832142[1000] valid_0's auc: 0.833035
INFO:__main__:elapsed time: 414.358 sec
INFO:__main__:ROC-AUC score: 0.833369
続いて CUDA を使って学習してみよう。
先ほどのサンプルコードの "device": "cpu" を "device": "cuda" に書き換えて実行する。
ROC-AUC の計算が CUDA には対応していないので CPU の処理にフォールバックしているけど、メトリックの計算に過ぎないので特に問題はないはず。
$ python3 benchmark.py
[LightGBM][Warning] Using sparse features with CUDA is currently not supported.
[LightGBM][Info] Number of positive: 3264308, number of negative: 2895691[LightGBM][Warning] Metric auc is not implemented in cuda version. Fall back to evaluation on CPU.
[LightGBM][Info] Total Bins 6132[LightGBM][Info] Number of data points in the train set: 6159999, number of used features: 28[LightGBM][Warning] Metric auc is not implemented in cuda version. Fall back to evaluation on CPU.
[LightGBM][Info][binary:BoostFromScore]: pavg=0.529920 ->initscore=0.119824[LightGBM][Info] Start training from score 0.119824[100] valid_0's auc: 0.811524[200] valid_0's auc: 0.819294[300] valid_0's auc: 0.822628[400] valid_0's auc: 0.825175[500] valid_0's auc: 0.826881[600] valid_0's auc: 0.82841[700] valid_0's auc: 0.829691[800] valid_0's auc: 0.83085[900] valid_0's auc: 0.832043[1000] valid_0's auc: 0.833091
INFO:__main__:elapsed time: 79.020 sec
INFO:__main__:ROC-AUC score: 0.833390
ただしデメリットもあって、搭載している CPU のアーキテクチャが Zen 3 なので、最新の Zen 4 に比べると一世代古い。
メーカーの Web サイト 1 を確認すると、発売日が 2021-06-01 なので 2 年前の CPU ということになる。
また、サポートしている PCIe のバージョンについても Gen3 なので、現在の主流である Gen4 に比べると遅くなる。
CPU の世代が新しい別のモデルは、もう少し価格が上がるので、ここは値段とのトレードオフになりそう。
とはいえ今回は、ベンチマークの結果なども考慮しつつ、用途に対して実用に耐えうると判断して購入するに至った。
今回のようにストレージを交換すると、当然ながら OS が空っぽになるのでリカバリの作業が必要になる。
Lenovo は Lenovo USB Recovery Creator というリカバリ用の USB メモリを作るための Windows 向けツールを提供している。
そのため、あらかじめ容量が 32GB 以上の USB メモリを購入しておこう。
あらかじめ作っておいたリカバリ用の USB メモリを筐体のポートに差し込んで電源を入れる。
リカバリを実行する前に、ストレージのデータが消去される旨の警告が表示されるので了承する。
その後は自動で処理が進むので、完了するのをひたすら待つだけ。
なお、筐体には USB 2.0 のポートもあるので、誤ってそこに USB メモリを差さないように注意しよう。
具体的には、イーサネットポート (RJ-45) に近い 2 つの USB ポートが USB 2.0 なので、別のポートを使う。
差しても動作に支障はないけど USB 3.0 のポートを使う場合と比べてリカバリにかかる時間が伸びてしまう。