-
Notifications
You must be signed in to change notification settings - Fork 37
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
Singularity launching support #101
Comments
After discussion within the team, we have reached consensus on the following approach: Container runtimes will be supported in a class hierarchy as shown: # container.py
class Container:
...
class Singularity(Container):
...
class Docker(Container):
...
class Podman(Container):
... Users will instantiate this class with all the relevant container information, such as path to image, container arguments, and paths to bind/mount (if they don't want to specify them as container args). Below is a simple example: # user-experiment.py
from smartsim.settings import container
s = container.Singularity('image.sif',
args='--nv', paths=['path/to/exp'])
# Container object is passed to RunSettings initializers
aprun = AprunSettings(exe, container=s) The image path may be a local or remote path (such as dockerhub / shub URL). The singularity args is a string of args to append to the singularity invocation. The paths to bind/mount can be given as a string (for 1 path), list (to expose each path without changing it within the container), or a dict (to map each path to a different path within the container). The default SmartSim will explicitly pass any environment variables that are required by SmartSim, such as We will add some additional getter/setter methods to modify the container data after instantiated. Also, some internal methods will support serialization of the container object for experiment tracking purposes down the road. Future work may support extending the high-level # Experiment takes container runtime and container image
exp.create_run_settings(exe, container_image=image, container='singularity')
# Automatically creates Container object
# Automatically binds experiment directory Here is a standalone example demonstrating the interface: from smartsim import Experiment
from smartsim.settings import container
# Create experiment
exp = Experiment(name="container-example")
# Create container object
s = container.Singularity('path/to/simulation_container.sif',
paths=['/path/to/exp', '/lus/datasets'],
args='--nv')
# Create RunSettings with container
settings = exp.create_run_settings(exe="./simulation.py", container=s)
# Create model
containerized_model = exp.create_model(name="containerized_simulation")
# Start experiment
experiment.start() |
[committed by @ben-albrecht] [reviewed by @ashao] This PR adds the ability for SmartSim to launch workloads in Singularity (Apptainer) as described in #101. It also lays the groundwork for supporting other container runtimes such as docker, shifter, and podman in the future, as well as launching the orchestrator in a container. ## Design Variations During development, it became clear that a few design changes from the original proposal were required. I have documented them below with their rationale: #### 1. Argument name: `bind_paths` -> `mount` The terms bind path and mount are mostly used interchangeably across different container runtimes. When writing tests, I kept forgetting if it was `bind_path` or `bind_paths`, which hinted to me that it was not a great arg name, so I swapped it out for the more succinct and easy to remember `mount`. #### 2. `create_run_settings(..., container: str)` -> `create_run_settings(..., container: Container)` We originally thought it would be easier for users to get started with containers by allowing them to pass a string into `create_run_settings(container='singularity')` instead of having to create a Container object. While writing tests, I realized that this was potentially very confusing for users because 1) the `container` arg types change between `create_run_settings` and `RunSettings`, and 2) if you need to add other metadata such as container args or container mount paths, you have to switch from using `create_run_settings` to `RunSettings` in your code, which is very annoying. Because creating Containers is so lightweight, I think it is best to keep the container interface consistent across all functions that accept them. #### 3. dropped getter/setter methods Because command generation and validation happens upon execution, users can freely modify `Container.args` and `Container.mount` without getter/setter methods to update any other state. Therefore, I dropped these methods from the interface. ## Testing Added 2 test suites for containers: One for WLM testing and one for local testing. The local testing suite runs in GitHub actions. Due to the added time from building Singularity and pulling the `container-testing` image, the singularity testing only happens on one configuration of the build matrix: python 3.9 + redisai 1.2.5 on linux
Description
SmartSim should be able to use
singularity
, specificallysingularity exec
to launch mpi applications that have been containerized. This should be able to work with a number of different run commands (i.e.srun singularity exec
.Justification
I will not list out the benefits of putting applications in containers because there are too many to list, however, SmartSim being able to launch such containers would be one more way SmartSim can contribute to reproducible science. Having each stage of a driver script be a containerized application could greatly benefit scientists in terms of sharing and reproducibility.
Implementation Strategy
I can think of two ways that this can be implemented.
RunSettings
child class.This approach would create a
SingularityRunSettings
class (possibly by a shorter name) that would take in the run command (i.e.srun
) and other run arguments. Based on the run command that is passed, a correspondingRunSettings
instance would be created in the class that all class methods that are typical forRunSettings
would pass to. For example:under the hood this would just pass the argument
10
to theAprunSettings
class created and held as an instance variable within theSingularityRunSettings
class.RunSettings
this method is likely easier since this method could be promoted to the
RunSettings
base class, but essentially this approach is a method that sets a flag for if something is to be launched as a singularity container.this method would do the following
Step
level)singularity
and exe_args to start withexec
Acceptance Criteria
The text was updated successfully, but these errors were encountered: