SDK commands
Multi-machine jobs
The MMT class in the Lightning SDK allows you to run multi-machine jobs asynchronously inside a Studio. Use this to offload tasks like data processing, training runs, or inference jobs that do not require interactive execution but multiple nodes communicating with each other.
The SDK is automatically available inside Studios. To use the SDK outside a Studio, install it with:
pip install --upgrade lightning-sdkEnsure you authenticate using environment variables or login via CLI.
export LIGHTNING_USER_ID=your-user-id
export LIGHTNING_API_KEY=your-api-keySubmit a MMT
Here is a full example of how to submit a multi-machine job.
# Install the Lightning SDK
# pip install lightning-sdk
# Export authentication variables
# export LIGHTNING_USER_ID=your-user-id
# export LIGHTNING_API_KEY=your-api-key
from lightning_sdk import Studio, Machine, MMT
# Step 1: Initialize a Studio
studio = Studio(name="batch-processing", teamspace="my-teamspace", user="my-user")
studio.start()
# Step 3: Run a Multi-machine job
job = MMT.run(command="python process_data.py", name="data-job", machine=Machine.CPU, studio=studio, num_machines=2)
# Step 4: Monitor Job Status
print(job.status) # Running, Completed, Failed
# Step 5: Stop or Delete a Job
# job.stop() # Gracefully stop a running job
# job.delete() # Cancel and remove the job
# Step 6: Shut Down the Studio
studio.stop()Initialize a Studio
Before running a job, first initialize and start a Studio:
from lightning_sdk import Studio
studio = Studio(name="batch-processing", teamspace="my-teamspace", user="my-user")
studio.start()Submit the Job
With the Studio defining the compute environment, submit the multi-machine job:
job = MMT.run(command="python process_data.py", name="data-job", machine=Machine.CPU, studio=studio, num_machines=2)List running multi-machine jobs
teamspace = Teamspace("my-teamspace", user="my-user")
for job in teamspace.multi_machine_jobs:
print(job.name, job.status)Check multi-machine status
job = MMT("data-job", teamspace="my-teamspace", user="my-user")
print(job.status) # Running, Completed, FailedStop or cancel a multi-machine job
If a job is no longer needed, you can stop or delete it:
job.stop() # Gracefully stops a job
job.delete() # Cancels and removes the jobRun multiple jobs in parallel
You can launch multiple jobs on different machine types:
MMT.run(command="python preprocess.py", name="preprocess", machine=Machine.CPU, studio=studio, num_machines=2)
MMT.run(command="python train.py", name="train-job", machine=Machine.A10G, studio=studio, num_machines=2)
MMT.run(command="python infer.py", name="inference", machine=Machine.L4, num_machines=2)Automate Jobs
GitHub actions
You can schedule jobs using GitHub Actions to run at a fixed time:
name: Scheduled Job
on:
schedule:
- cron: '0 3 * * *' # Runs at 3 AM UTC daily
jobs:
run_batch:
runs-on: ubuntu-22.04
steps:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.10"
- name: Install Lightning SDK
run: pip install lightning-sdk
- name: Start a Job
run: |
python -c " \
from lightning_sdk import Studio, MMT, Machine; \
studio = Studio(name='batch-pipeline', teamspace='my-team', user='ci-bot'); \
studio.start(); \
MMT.run(command='python daily_task.py', name='daily-task', studio=studio, machine=Machine.A10, num_machines=2); \
studio.stop();"
env:
LIGHTNING_USER_ID: ${{ secrets.LIGHTNING_USER_ID }}
LIGHTNING_API_KEY: ${{ secrets.LIGHTNING_API_KEY }}- Use CPU machines for lightweight preprocessing tasks.
- Use GPU machines for deep learning inference and training.
- Enable interruptible mode for cost-saving on long-running multi-machine jobs.
- Chain multi-machine jobs using status checks to create multi-step pipelines.
API Reference
__init__()
The init() method fetches an existing multi-machine job and accepts the following arguments:
| Parameter | Type | Description | Default |
|---|---|---|---|
| name | str | The name of the Job | - |
| teamspace | str | Teamspace | The teamspace the job is part of |
| org | str | Organization | The name of the organization owning the teamspace in case it is owned by an org |
| user | str | User | The name of the user owning the teamspace in case it is owned by a user instead of an org |
Example:
job = MMT("data-job", teamspace="my-teamspace", user="my-user")run()
The run() method submits a new multi-machine job and accepts the following arguments:
| Parameter | Type | Description | Default |
|---|---|---|---|
| name | str | The name of the job | - |
| machine | Machine | Machine to run the Job on | - |
| num_machines | int | The number of machines to run the job on | - |
| command | str | The command to run inside the Studio | None, The command to run inside your job. Required is using a Studio as compute environment. Optional for docker jobs. In case it's not specified for docker jobs, these will run the default command specified by the image. |
| studio | Studio | str | None |
| image | str | None | The docker image to run the job with. Mutually exclusive with studio. |
| teamspace | Teamspace | str | None |
| org | str | Organization | None |
| user | str | User | None |
| cloud_account | str | None | The cloud acocunt to run the job on |
| env | Dict[str, str] | None | Environment variables to set inside the job. |
| interruptible | bool | Whether the job should run on interruptible instances. They are cheaper but can be preempted. | False |
| image_credentials | str | None | The credentials used to pull the image. Required if the image is private. This should be the name of the respective credentials secret created on the Lightning AI platform. |
| cloud_account_auth | bool | Whether to authenticate with the cloud account to pull the image. Required if the registry is part of a cloud provider (e.g. ECR). | False |
| entrypoint | str | The entrypoint of your docker container. To use the pre-defined entrypoint of the provided image, set this to an empty string. Only applicable when submitting docker jobs. | "sh -c", which just runs the provided command in a standard shell. |
| path_mappings | Dict[str, str] | None | Dictionary of path mappings. The keys are the path inside the container whereas the value represents the data-connection name and the path inside that connection. Should be of form{ " |
Example:
job = MMT.run(command="python process_data.py", name="data-job", machine=Machine.T4, num_machines=2, studio=studio)stop()
Stops the respective job. Accepts no arguments.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
job.stop()delete()
Deletes the respective multi-machine job. Note that this also deletes all respective artifacts and is non-reversible. Accepts no arguments.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
job.delete()status
Property returning the current status of the multi-machine job.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
print(job.status) # -> Status.Pending, Status.Running, Status.Completed, Status.Stopped, Status.Failedmachine
Property returning the machine the multi-machine job is/was running on.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
print(job.machine) # -> Machine.A10Gmachines
Property returning objects referring to the individual machines the job is running on
artifacts_uri
Always None on a multi-machine job: each machine has its own artifacts, so there is no single address. Read one machine's address from machine.artifacts_uri, or use list_artifacts() and download_artifacts() below.
Each machine resolves its own address exactly as a single-machine job does, giving three outcomes:
- A Studio-backed machine writes to
jobs/<job-name>-<rank>. - A machine running a container image launched with
artifacts_destinationwrites to the connection it names, at<type>_connections/<name>/<path>. - A machine running a container image launched without one keeps no artifacts, and its
artifacts_uriisNone.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
for machine in job.machines:
# "lit://my-org/my-teamspace/jobs/data-job-0" Studio-backed
# "lit://my-org/my-teamspace/s3_connections/my-bucket/run-7" container + artifacts_destination
# None container, no artifacts_destination
print(machine.artifacts_uri)list_artifacts()
Lists what the job wrote to the teamspace drive, across every machine. Returns one entry per file or folder, each with a path, is_dir, size and last_modified. Every path is prefixed with the name of the machine that wrote it, so the listing and download_artifacts() agree. A machine that keeps no artifacts contributes no entries, so the list is empty for a container-image job launched without artifacts_destination.
| Parameter | Type | Description | Default |
|---|---|---|---|
| path | str | Subfolder of each machine's artifacts to list. | "", all of them |
| recursive | bool | Whether to descend into subfolders. | False |
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
for entry in job.list_artifacts(recursive=True):
if not entry.is_dir:
print(f"{entry.path} ({entry.size} bytes)") # -> "data-job-0/metrics.json (1024 bytes)"download_artifacts()
Downloads what the job wrote to a local directory, giving each machine a folder named after it.
Raises RuntimeError at the first machine that keeps no artifacts — every machine of a container-image job launched without artifacts_destination. The machines are taken in rank order, so the error can surface after earlier ones have already downloaded.
| Parameter | Type | Description | Default |
|---|---|---|---|
| target_dir | str | Path | Local directory to download into. Created if it does not exist. | ".", the working directory |
| path | str | Subfolder of each machine's artifacts to download. | "", all of them |
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
job.download_artifacts("./artifacts") # -> ./artifacts/data-job-0, ./artifacts/data-job-1, ...
# Take one subfolder, so a long run does not have to come down whole
job.download_artifacts("./checkpoints", path="checkpoints")name
Property returning the name of the multi-machine job.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
print(job.name) # -> "data-job"teamspace
Property returning the teamspace the multi-machine job belongs to.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
print(job.teamspace) # -> Teamspace("my-teamspace", org="my-org")studio
Property returning the studio used as compute environment if it wasn't launched with a docker image.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
print(job.studio) # -> Studio("my-studio", teamspace="my-teamspace", org="my-org") or Noneimage
Property returning the image used as compute environment if it wasn't launched with a Studio.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
print(job.image) # -> "ubuntu:latest" or Nonecommand
Property returning the command ran within the multi-machine job.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
print(job.command) # -> "python train.py"logs
Property returning the logs generated by running the multi-machine job. Will return an error if the job is still pending or running (check job.status)
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
print(job.logs) # -> "Epoch 1/2: ################"link
Property returning the link to view the job in the UI.
Example:
job = MMT("data-job", teamspace="my-teamspace", org="my-org")
print(job.link) # -> "https://lightning.ai/my-org/my-teamspace/studios/my-studio/app?app_id=jobs&job_name=data-job"Was this page helpful?
Thanks for the feedback.