-
Notifications
You must be signed in to change notification settings - Fork 11
Add the legacy runtime backend #130
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
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
c3f6d97
feat: add new `JobStatusInfo` model
AlexJones0 46d8ecc
feat: introduce `JobSpec.id` property
AlexJones0 8ee0523
feat: introduce abstract `RuntimeBackend` base class
AlexJones0 806d40f
feat: introduce `LegacyLauncherAdapter` runtime backend
AlexJones0 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Copyright lowRISC contributors (OpenTitan project). | ||
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """Job runtime backends.""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| # Copyright lowRISC contributors (OpenTitan project). | ||
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """Runtime backend abstract base class.""" | ||
|
|
||
| from abc import ABC, abstractmethod | ||
| from collections.abc import Hashable, Iterable | ||
|
|
||
| from dvsim.job.data import JobSpec | ||
| from dvsim.job.status import JobStatus | ||
| from dvsim.logging import log | ||
| from dvsim.runtime.data import ( | ||
| CompletionCallback, | ||
| JobCompletionEvent, | ||
| JobHandle, | ||
| ) | ||
|
|
||
|
|
||
| class RuntimeBackend(ABC): | ||
| """Abstraction for a backend that launches, maintains, polls and kills a job. | ||
|
|
||
| Provides methods to prepare an environment for running a job, launching the job, | ||
| polling for its completion, killing it, and doing some cleanup activities. | ||
| """ | ||
|
|
||
| name: str | ||
| """The name of the backend.""" | ||
|
|
||
| max_parallelism: int = 0 | ||
| """The maximum number of jobs that can be run at any time via this backend. The scheduler | ||
| should respect the parallelism limit defined here. | ||
| """ | ||
|
|
||
| max_output_dirs: int = 5 | ||
| """If a history of previous invocations is to be maintained, keep at most this many dirs.""" | ||
|
|
||
| supports_interactive: bool = False | ||
| """Whether this backend supports jobs in interactive mode (transparent stdin/stdout).""" | ||
|
|
||
| def __init__(self, *, max_parallelism: int | None = None) -> None: | ||
| """Construct a runtime backend. | ||
|
|
||
| Args: | ||
| max_parallelism: The maximum number of jobs that can be dispatched to this backend | ||
| at once. `0` means no limit, `None` means no override is applied to the default. | ||
|
|
||
| """ | ||
| if max_parallelism is not None: | ||
| self.max_parallelism = max_parallelism | ||
|
|
||
| self._completion_callback: CompletionCallback | None = None | ||
|
|
||
| def attach_completion_callback(self, callback: CompletionCallback) -> None: | ||
| """Attach a callback for completed events, to notify the scheduler. | ||
|
|
||
| Args: | ||
| callback: the callback to use for job completion events. | ||
|
|
||
| """ | ||
| self._completion_callback = callback | ||
|
|
||
| async def _emit_completion(self, events: Iterable[JobCompletionEvent]) -> None: | ||
| """Mark a job as now being in some completed/terminal state by notifying the scheduler.""" | ||
| if self._completion_callback is None: | ||
| raise RuntimeError("Backend not attached to the scheduler") | ||
|
|
||
| for event in events: | ||
| log.debug( | ||
| "Job %s completed execution: %s", event.spec.qual_name, event.status.shorthand | ||
| ) | ||
| if event.status != JobStatus.PASSED and event.reason is not None: | ||
| log.verbose( | ||
| "Job %s has status '%s' instead of 'Passed'. Reason: %s", | ||
| event.spec.qual_name, | ||
| event.status.name.capitalize(), | ||
| event.reason.message, | ||
| ) | ||
|
|
||
| await self._completion_callback(events) | ||
|
|
||
| @abstractmethod | ||
| async def submit_many(self, jobs: Iterable[JobSpec]) -> dict[Hashable, JobHandle]: | ||
| """Submit & launch multiple jobs. | ||
|
|
||
| Returns: | ||
| mapping from job.id -> JobHandle. Entries are only present for jobs that successfully | ||
| launched; jobs that failed in a non-fatal way are missing, and should be retried. | ||
|
|
||
| """ | ||
|
|
||
| async def submit(self, job: JobSpec) -> JobHandle | None: | ||
|
AlexJones0 marked this conversation as resolved.
|
||
| """Submit & launch a job, returning a handle for that job. | ||
|
|
||
| If the job failed to launch in a non-fatal way (e.g. backend is busy), None is returned | ||
| instead, and the job should be re-submitted at some later time. | ||
| """ | ||
| result = await self.submit_many([job]) | ||
| return result.get(job.id) | ||
|
|
||
| @abstractmethod | ||
| async def kill_many(self, handles: Iterable[JobHandle]) -> None: | ||
| """Cancel ongoing jobs via their handle. Killed jobs should still "complete".""" | ||
|
|
||
| async def kill(self, handle: JobHandle) -> None: | ||
| """Cancel an ongoing job via its handle. Killed jobs should still "complete".""" | ||
| await self.kill_many([handle]) | ||
|
|
||
| async def close(self) -> None: # noqa: B027 | ||
| """Release any resources that the backend holds; called when the scheduler completes. | ||
|
|
||
| The default implementation just does nothing. | ||
|
|
||
| """ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # Copyright lowRISC contributors (OpenTitan project). | ||
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """Various dataclasses used by the different runtime backends when executing jobs.""" | ||
|
|
||
| from collections.abc import Awaitable, Callable, Hashable, Iterable | ||
| from dataclasses import dataclass | ||
| from typing import TypeAlias | ||
|
|
||
| from dvsim.job.data import JobSpec, JobStatusInfo | ||
| from dvsim.job.status import JobStatus | ||
| from dvsim.job.time import JobTime | ||
|
|
||
| __all__ = ( | ||
| "CompletionCallback", | ||
| "JobCompletionEvent", | ||
| "JobHandle", | ||
| ) | ||
|
|
||
|
|
||
| @dataclass(kw_only=True) | ||
| class JobHandle: | ||
| """A handle for a job that is actively executing on some backend.""" | ||
|
|
||
| spec: JobSpec | ||
| backend: str | ||
|
|
||
| # TODO: these are necessary for now because they are exposed in the CompletedJobStatus. | ||
| # It would be nice to figure out a better mechanism for these. | ||
| job_runtime: JobTime | ||
| simulated_time: JobTime | ||
|
|
||
| @property | ||
| def job_id(self) -> Hashable: | ||
| """Returns an object that uniquely identifies the job. Alias of self.spec.id.""" | ||
| return self.spec.id | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class JobCompletionEvent: | ||
| """Event emitted when a job finishes.""" | ||
|
|
||
| # TODO: ideally we would rather store a `job_id: Hashable` here instead of the full spec, but | ||
| # this is needed to access the `post_finish` callback in `RuntimeBackend._emit_completion`. | ||
| # When these `pre_launch`/`post_finish` callbacks are refactored/removed, this can be changed. | ||
| spec: JobSpec | ||
| """The specification for the job that has been completed.""" | ||
| status: JobStatus | ||
| """The terminal/final status of the completed job.""" | ||
| reason: JobStatusInfo | None | ||
|
AlexJones0 marked this conversation as resolved.
|
||
| """The reason to report as to why the job is in the specified terminal state. | ||
| Typically only reported for non-successful executions, as it is used for e.g. failure message | ||
| buckets - success is implicit. | ||
| """ | ||
|
|
||
|
|
||
| # Callback (async) for (batches of) job completion events | ||
| CompletionCallback: TypeAlias = Callable[[Iterable[JobCompletionEvent]], Awaitable[None]] | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.