Restart cluster job on task completion
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 25/100
- issue の種類
- 機能追加
- 明瞭さ
- 説明が足りない
- 活発さ
- 停滞
- 技術スタック
- python
調査の方向性
SLURMCluster の設定と、issue にある WorkerPlugin および client.retire_workers の例から始めます。それらの worker のライフサイクルとタスクのバランシング動作を、提案されている scheduler-plugin アプローチと比較します。完了の定義は、タスク完了後に worker を、タスクを繰り返したり walltime の直前に作業を開始したりすることなく、停止または再起動するための、文書化されサポートされた方法があることです。
索引モデルが issue の本文から書いたものです。
説明
Use case conditions:
- tasks have large and variable run times
- task executes 3rd party software, such that dask cannot migrate the execution state
- workers have a wall time eg HPC cluster
Current behavior:
Compute is wasted on tasks that cannot finish in remaining walltime, task is restarted from scratch on new worker after worker death.
Originally working with this issue on the forums here
More context:
Task executes a 3rd party software (mine requiring multiple threads, see the issues linked in the above post for examples). Code looks something like the following:
import dask
from dask_jobqueue import SLURMCluster
from distributed import Client
import distributed
import logging
import time
def do_one(x):
worker = distributed.get_worker()
logger = logging.getLogger('worker')
logger.setLevel(logging.INFO)
fh = logging.FileHandler(f'worker_{worker.id}.log', mode='w')
fh.setLevel(logging.INFO)
logger.addHandler(fh)
logger.info(f"I am working on {x}")
# run third party software
# this takes a while but is not very consistent in total time
logger.info(f"I finished {x}")
return f"Input {x} done"
if __name__ =='__main__':
cluster = SLURMCluster(
memory="1g",
walltime='00:30:00',
job_extra_directives=['--nodes=1', '--ntasks-per-node=1'],
cores=1,
processes=1,
worker_extra_args=["--lifetime", "28m", "--lifetime-stagger", "50s"],
job_cpu=6
)
cluster.adapt(minimum=2, maximum=10)
client = Client(cluster)
results = []
for future in distributed.as_completed(client.map(
do_one, list(range(100,132))
)):
result = future.result()
results.append(result)
Result of worker_XXX.log
2022-11-07-12:00:00 INFO I am working on 1
2022-11-07-12:22:00 INFO I finished 1
2022-11-07-12:22:03 INFO I am working on 10
Worker XXX is killed at 12:29 due to walltime. 7 minutes of compute is wasted because the state cannot be changed. Task 10 starts from scratch on a new worker.
Attempts to fix:
Short of figuring out a way to move the execution state, I figure the best strategy is to have each task get a brand new SLURM job, so that no compute is wasted and any task that can finish in the walltime works.
- I tried a worker plugin like so:
class KillerNannyPlugin(distributed.diagnostics.plugin.WorkerPlugin):
"""Better as a nanny plugin but those are not running transitions properly."""
def __init__(self, max_stagger_seconds: float = 5):
self.max_stagger_seconds = max_stagger_seconds
def setup(self, worker):
self.worker = worker
def transition(self, key, start, finish, *args, **kwargs):
if start == 'memory' and finish == 'released':
self.worker.io_loop.call_later(3+random.random() * self.max_stagger_seconds, self.worker.close_gracefully, restart=True)
- This was successful in ensuring each task got its own job, but caused task repeat to be on the order of 100%, defeating the point of saving compute
- Have the client retire the worker that just completed a task when the job is done, like so:
for future in distributed.as_completed(client.map(
do_one, list(range(100,132))
)):
who_has = client.who_has(future)
closing = list(list(who_has.values())[0])
client.retire_workers(closing)
- I also added a small time delay to the worker function such that next tasks did not start (and begin wasting energy) while the client retired the worked.
- This seems to have the desired effect, any consequences of this are not clear to me as I observe that tasks are not repeated nor do tasks start on a job that is about to time out.
I think this should be codified somehow as the "solution" above is quite hacky. My intuition says that it would fit best as a scheduler plugin, as using the worker plugin above clearly had adverse effects on task balancing. Happy to help contribute with some input on where this would fit best if it would be a useful addition.
- 主要言語
- Python
- スター
- 256
- フォーク
- 148
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
dask/dask-jobqueue のほかの issue
-
bug LSF
難易度 3/5 1〜2日 初心者へのやさしさ 65/100
dask/dask-jobqueue#703 · コメント 1 件 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
dask/dask-jobqueue#701 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 45/100
dask/dask-jobqueue#699 · コメント 2 件 ·
-
bug
難易度 3/5 1〜2日 初心者へのやさしさ 38/100
dask/dask-jobqueue#692 · コメント 1 件 ·
-
bug
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
dask/dask-jobqueue#691 · コメント 7 件 ·
dask/dask-jobqueue の issue をすべて見る
似ている issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
521xueweihan/HelloGitHub#4115 ·
-
get_lldp_neighbors_detail: query asks for 'max-address' (typo for 'mac-address'), so remote_chassis_id is always empty対応中かも @Jah-yee が今日担当しました。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
-
lesson-submission pending-review
難易度 1/5 1時間未満 初心者へのやさしさ 74/100
Ikalus1988/MisakaNet#3899 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
aws-samples/sample-per-model-bedrock#549 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 90/100