😸

ローカルのホストでも競技プログラミング並みに厳しい環境でやってみたい

2022/11/20に公開

競技プログラミングだとメモリ1024M, cpu 実行時間2秒など過酷な
時間でやることになります。

これは我々が普段使いしているPCと全然スペックが違います。
競技プログラミングのスペックなら一生帰って来ないようなものでも
我々のPCだと一瞬で結果が帰ってきたり。

dockerなどの仮想環境だと制限以外の部分で重くなるし、
競技プログラミングと同じリソース環境でやりたいがメインなら大げさ過ぎです。

ということで簡単にリソースを絞る方法をここに書きます。

準備

cpuの個数の制限にtasksetを使いますが、いちいちsudoが求められます。
普段使いするなら面倒臭いですし、sudoの権限を与えるのが嫌なら次のように
doasで設定しておきましょう。
使ったことが無いなら、doasは今後linux界隈でも使われることが多くなると
思うのでこの際使い方を覚えてください。ほぼすべてのディストリビューションでdoasは使えます。

仮想環境や、ネットワークの設定など頻繁に使う用のユーザーなら
設定しておくと便利です。

/etc/doas.conf
# ex) permit nopass username as root cmd virtualbox

# taskset commandを頻繁に使うので設定
permit nopass username as root cmd taskset

これは「usernameに対してパスワード無しでrootユーザーとしてtasksetコマンドの実行許可を与えます。」
という意味になります。

usernameの部分をリソース制限用スクリプトを実行したいユーザーに置き換えて
設定してください。

実行時はsudoと同じように使いたいコマンドの前にdoasと書くだけです。

# ex) doasでaptコマンドを許可している場合
doas apt update
doas apt upgrade 

OpenBSD本家 doasの使い方
Archwiki doasの使い方

doasはOpenBSDプロジェクトの成果物です。

リソース制限用スクリプト

現在のプロセスに対してリソースの制限を行います。

limited.sh
#!/usr/bin/env bash
#
# 現在のプロセスをatcorderの指定通りにメモリ、実行時間を制限する
# source でファイルを読み込んでください。

# プロセス全体で使えるメモリを1024 * 1024 キロバイト = 1024Mバイトに制限
ulimit -m $((1024 * 1024))
# ulimit -v $((1024 * 1024))

# 実行時間制限を2秒に設定
ulimit -t 2

# 現在のプロセスに対してtasksetで0番のcpuのみ割り当てる。
# sudoでも良いが、簡単に使いたい。
doas taskset -p 0 $$

下のようにsourceコマンドで読み込んで、現在のプロセスとして実行してください。
普通に実行だとbashが別にプロセスを立ち上げて実行するため、実行中のシェルに反映されません。

source limited.sh

リソース制限のチェック

下のスクリプトファイルを実行してください。

limited_check.sh
#!/usr/bin/env bash
#
# メモリ、cpu実行時間、cpu番号制限チェック

for ((i = 1; i <= $((10**7)); i++)); do
  echo $i
done

リソースが切れたら、killedと表示されて、途中で処理が中断されるはずです。

まとめ

割と簡単に設定することができたと思います。

ただ、cpuやメモリのハードウェア自体の性能の差で早い、遅いは
まだあるので、そこは我慢。
あくまで目安ね。

Discussion