Replies: 1 comment
-
|
Use case: I was building a job that would have benefited from this feature this week. I need a job that runs a task for each object under an S3 prefix. For now, I made a Python script that discovers the S3 objects then creates a job based on the discovered objects. I wanted to use Deadline's job bundle submitter with this job but can't because the Python script needs to run before the template exists. It would be much better to have a self-contained job with discovery step which finds the S3 objects then a processing step which is parameterized over those objects. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Introduction
An early topic of discussion about Open Job Description templates was Immutability vs. dynamic adjustments. An important point is about cases where you don't know the full job structure at job submission time, either because that information is embedded in the input data files and hard to extract, or because that information requires some kind of computation to determine it.
This is an idea to add a new VAR_DATA_FLOW extension to the template specification. It depends on the EXPR extension (#79) for the expression language needed to reference step output variables. It also works well together with the idea for conditionally enabling/disabling a step via an expression (#81). A step's
enableIffield could reference an output variable from an upstream step, allowing the job structure to adapt based on computed results.Example 1: Video processing with a computed frame count
Consider a video processing example to process it frame-by-frame. The job submission context may or may not have the video file locally, and even if it does it may not have a program that can accurately and rapidly determine the frame count. The step that does per-frame processing needs a parameter space like "1-{FrameCount}", with a structure kind of like this:
In this example, the first step produces a scalar value (FrameCount) that determines the size of the second step's parameter space. The job structure — three sequential steps — is known at submission time, but the task count of the middle step is not.
Example 2: Distributed spatial processing with a computed DAG
Consider a distributed spatial processing algorithm on a 3D scene, such as hierarchical lightmap baking, global illumination, or spatial partitioning. The scene graph needs to be analyzed first to determine how to break it into subparts and what order to process them in. This analysis produces a DAG (directed acyclic graph) of processing tasks with dependency edges — for example, leaf nodes of a spatial hierarchy can be processed in parallel, but parent nodes must wait for their children.
We can run this kind of job by extending the idea from the video processing example — but here the first step produces not just a scalar, but an entire graph structure that defines both the task count and the interior task-task dependency structure of the next step.
The Idea for RFC to represent task-task dependencies (#82) proposes a
dependsOnSubspacemechanism and shows a DAG example using aLIST[LIST[INT]]job parameter as an adjacency list. That discussion's example assumes the adjacency list is known at submission time and provided as a job parameter default. This proposal extends that: the adjacency list is computed by a prior step and flows along the step dependency edge.In the notation from #82, the second step would look something like:
This differs from the DAG example in #82 in a key way: there,
Param.GraphAdjListis a job parameter with a known default. Here, both the adjacency list and the node count come from the output of a prior step. The job template author knows the shape of the job (analyze, then process as a DAG) but not the size or structure of the DAG until the analysis step runs.This example also shows that the data flowing along a step dependency isn't limited to simple scalars — it can be structured data like
LIST[LIST[INT]], which requires the type extensions proposed in #79.Idea
openjd_output_var: var_name=<JSON value convertible the var_name's type>. This is similar to how environments can set environment variables.Here's an end-to-end example of the video processing job (Example 1) showing all of these working together. It also uses the expression language syntax from #79.
The new pieces in this template are:
outputVariableson the VideoToFrames step — declares that this step will produce anINTvariable calledFrameCount. This is part of the template's static structure, so a scheduler or validator can check that downstream references likeStep.VideoToFrames.FrameCountare well-typed before any task runs.openjd_output_var: FrameCount=...in the script — the runtime mechanism by which the running task actually sets the value, analogous to howopenjd_envsets environment variables in an Environment's onEnter action.Step.VideoToFrames.FrameCountin the ProcessFrames parameter space range — a new value reference that reads the output variable from a completed upstream step. The scheduler knows it cannot evaluate this expression (and therefore cannot create tasks for ProcessFrames) until VideoToFrames has finished.Beta Was this translation helpful? Give feedback.
All reactions