GCJ Round 1Aに出てメモリエラー(?)にハマってしまったのでメモ。
Square Danceのhiddenを落としてしまったのだが、ローカルでいろいろ調べても落ちるケースが見つからない。テストサブミットでしつこく調べていると、どうも入力が大きい時に無条件で落ちているようだった。まさかと思って、dynamic-space-size
を増やしたSBCLを別に起動して投げてみたら通った。ヘッダを以下のようにする:
(unless (member :child-sbcl *features*)
(quit
:recklessly-p t
:unix-status
(process-exit-code
(run-program *runtime-pathname*
`("--control-stack-size" "128MB"
"--dynamic-space-size" "8GB"
"--noinform" "--disable-ldb" "--lose-on-corruption" "--end-runtime-options"
"--eval" "(push :child-sbcl *features*)"
"--script" ,(namestring *load-pathname*))
:output t :error t :input t))))
必要なサイズを調べてみると
- 1GBに設定 → 落ちる
- 2GBに設定 → テストケースごとに
gc
すれば通る - 4GBに設定 → 一回
gc
すれば通る - 8GB、16GBに設定 →
gc
しなくても通る
という感じだった。
しかし、メモリ制約が1GBなのに8GBが必要なのは不可解ではある。たまに起こる現象として、使用量500MBあたりで新たにメモリを確保しようとするときに、1GB以上確保しようとしてheap exhaustedになるというのがあるが、それは2GBや4GBに設定してもだめな理由を説明していない。そもそも、room
とかで調べてもそんなにたくさんメモリを使っているようには見えないし…… ローカルでroswellのsbcl-bin/1.3.14を使っても起きない問題なので、調べるのが難しい。
次のroundの方針は迷うけれど、
- 最初から
dynamice-space-size
を大きめに設定する。(とりあえず16GB?) - 1つ目のテストケースの前に
(gc :full t)
する。(コンパイルでけっこうメモリを使うので) - テストケース数が多すぎなければ一回ごとに
gc
する。
でいくことにする。
SBCL環境
GCJ 2020のSBCLの詳細は以下の通り:
- バージョン1.3.14、64-bit (debianのパッケージ)
- 事前コンパイルなし(おそらく
--script
で実行される) - スタックサイズを増やすテクニックは使える
事前コンパイルはないが、今年も長めのTLでまとめてテストするスタイルなので、コンパイル時間のぶんのロスは気にしなくてよさそう。
上の問題は不運ではあったけれど、そもそもPascal Walkをバグらせてしまったのが悪いとも言える。チャンスはまだあるので、早めに気づけてよかった。