Add Analysis design doc#446
Conversation
| ``` | ||
|
|
||
| The factory registers all combinations of scalar type (I4/I8/R4/R8), rank | ||
| (1–5), and memory location (Device/Host/Both) for each operator template: |
There was a problem hiding this comment.
For my understanding, why is it important to support both device and host locations? Is it that the actual operations would be conducted on the device but we would accept inputs that originate on the host and are copied to device within the operator?
There was a problem hiding this comment.
Actually, after thinking it over, I'm leaning towards not supporting HostArray types. Given that the compute work is currently done almost exclusively with ArrayDDTT types (ArrayMemLoc::Device arrays for GPU builds and ArrayMemLoc::Both for CPU-only builds), supporting HostArrayDDTT (ArrayMemLoc::Host) seems unnecessary right now, especially given deadlines.
Adding HostArray support to the analysis code would significantly increase code bloat and complexity. This would require either:
- memory transfers (as you mention). This would also complicate the operator templating, since output arrays could no longer be straightforwardly templated off the input arrays
- branching compute methods. Each operator compute method would require if-else branches, with duplicate code for kokkos kernels or ordinary loops depending on ArrayMemLoc.
If a compelling need comes up later, we can add this support then. The analysis module will continue to evolve after the immediate delivery, so I think we can avoid adding in this extra complexity prematurely.
There was a problem hiding this comment.
Sounds good. I support this simpler path.
| - `NormalVelocity_SpatialMean_TimeMean1day` — 1-day time average of the | ||
| spatial mean of NormalVelocity |
There was a problem hiding this comment.
This suggests that the order of operations is generally reversed in the name. Is that correct (or is the convention stated somewhere in this doc)?
There was a problem hiding this comment.
The order of operations here is parsed from left to right. So this translates to:
Fetch the NormalVelocity field -> Apply the SpatialMeanOp across the mesh -> Accumulate the average NormalVelocity value into the TimeMeanOp
By default for now the accumulation interval is the time step, so this whole chain is computed each time step. After a day passes the accumulated values in the TimeMeanOp are finalized by dividing by number of accumulation steps.
This is implied by the pattern: FieldName_Op1[Params]_Op2[Params]... in 4.2, but I could add a statement that makes the order more explicit.
There was a problem hiding this comment.
I think your pattern is probably sufficient for the design doc and we can just make this explicit when we write the user doc. Thanks!
There was a problem hiding this comment.
This also answers my question above -- we accumulate every time step for now. Make sense to me.
cbegeman
left a comment
There was a problem hiding this comment.
@brian-oneill It's clear you've given this a lot of thought! I don't have much feedback to offer, it's looking like a good plan to me.
sbrus89
left a comment
There was a problem hiding this comment.
@brian-oneill, this looks great. I just had a few comments mainly for my own understanding. Thanks for putting this capability together!
| \mathcal{O}_m\} \leftarrow \texttt{parseOperatorChain}(a)$ | ||
| - **For** $i = 1$ to $m$: | ||
| - Compute signature: $s \leftarrow \text{sig}(\mathcal{O}_i)$ | ||
| - **If** $s \in \Sigma$ (operator already exists): |
There was a problem hiding this comment.
I don't think \Sigma has been defined, is it the same as sig?
There was a problem hiding this comment.
It's the signature cache, the parenthesis in line 160 first references it. How exactly this will be ultimately be implemented is to be determined, it's essentially a list of strings that fully define unique operator instances.
| 2. Extract `ArrayDataType`, rank, and `ArrayMemLoc` from Field metadata | ||
| 3. Build fully-qualified type key: `OpType + "_" + ArrayTypeName + "_" + MemLoc` | ||
| 4. Look up constructor in registry; abort if not found | ||
| 5. Invoke constructor with `(UpstreamNames, Options)` and return result |
There was a problem hiding this comment.
What are UpstreamNames and Options?
There was a problem hiding this comment.
The example SpatailMaxOp in 4.1.2 shows an example of the constructor for the derived operators. UpstreamNames is a vector of strings, the names of any input fields to the operator. Options is a Config object. It can be the actual Config read from omega.yml, or I also describe a method for creating temporary Configs for passing parameters needed by an operator during construction, for example on line 466:
// Usage: makeOpConfig(opParam("Period", "1day"), opParam("Layer", 10))
| - **If** $\text{alarm} \notin u.\text{ComputeAlarms}$: | ||
| - $u.\text{ComputeAlarms} \leftarrow | ||
| u.\text{ComputeAlarms} \cup \{\text{Alarm}\}$ | ||
| (upstream nodes observe all downstream alarms) |
There was a problem hiding this comment.
I probably just missed it somewhere, but how/when are the additional output alarms assigned to terminal operators?
There was a problem hiding this comment.
Each AnalysisGroup can have 1 or more streams based on configuration, and each stream has a separate output alarm. The example GlobalStats config in the doc has time-averaging periods of 1 day and 1 month, as well as instantaneous snapshots every hour. So three streams get created with alarms with those frequencies, and the terminal operators in the group all get those alarms, which are then propagated to upstream operators.
| Fields: ["NormalVelocity", "Temperature", "Salinity"] | ||
| SpatialStats: ["Max", "Min", "Mean", "StdDev"] | ||
| ReductionPeriod: ["1Day", "1Month"] |
There was a problem hiding this comment.
Just to check if I'm understanding this correctly, but this GlobalStats group would produce 24 different output variables?
There was a problem hiding this comment.
Each stream would have 12 outputs, and the group config would create 3 streams: 1 Day averages, 1 Month averages, and 1 Hour Snapshots, so 36 total outputs.
The SampleFreq: ["1Hour"] option is intended to mean discrete sampling i.e., instantaneous snapshots output every hour. The label SampleFreq was one thing I was unsure of. It is a little ambigous because it could be interpreted as an accumulation interval for the temporal averages. Maybe SnapshotFreq would be better?
There was a problem hiding this comment.
This may just be an example for generality. But I would expect that we don't want any temporal statistic done on global stats, just spatial stats. They are snapshots in time.
There was a problem hiding this comment.
I agree that SnapshotFreq is better than SampleFreq because I assumed that this was indeed the computation interval for temporal stats.
There was a problem hiding this comment.
How is the computation interval set (if it is not every time step)?
| - `PseudoThickness_SpatialStdDev` — spatial standard deviation of | ||
| PseudoThickness (implicitly requires `PseudoThickness_SpatialMean` as a | ||
| shared intermediate) | ||
|
|
There was a problem hiding this comment.
I'm assuming that PseudoThickness_SpatialMean would get created automatically if only PseudoThickness_SpatialStdDev is specified. Would this happen because the SpatialStdDev operator class has a SpatialMean member? Or does the orchestrator handle adding adding a SpatialMean node/dependency?
There was a problem hiding this comment.
Ultimately yes, the dependencies would automatically be created. In my current implementation however, the mean needs to be explicitly specified first in order to use the std dev. This is because the PseudoThickness_SpatialMean operator needs to exist when the PseudoThickness_SpatialStdDev is being created. Otherwise, an error during initialization will occur when trying to fetch the PseudoThickness_SpatialMean Field. How to implement these kinds of more complex dependencies automatically is still to be worked out.
| Field does not already exist — enabling natural sharing of intermediate | ||
| results without an explicit signature cache. | ||
|
|
||
| > **Note on operator chain syntax**: The exact form of operator chain strings |
There was a problem hiding this comment.
Are there checks in place for invalid chains?
There was a problem hiding this comment.
Yes, if a substring from the chain doesn't exist as a Field, or there is no corresponding operator with that name, ABORT_ERROR will be called during initialization.
|
Sorry @brian-oneill, I didn't get to this one today. I'll get to it tomorrow. |
xylar
left a comment
There was a problem hiding this comment.
This looks good to me. Thank you @brian-oneill for the hard work on this. I think the current design is exactly the right combination of practical for now and forward-looking.
| Fields: ["NormalVelocity", "Temperature", "Salinity"] | ||
| SpatialStats: ["Max", "Min", "Mean", "StdDev"] | ||
| ReductionPeriod: ["1Day", "1Month"] |
There was a problem hiding this comment.
This may just be an example for generality. But I would expect that we don't want any temporal statistic done on global stats, just spatial stats. They are snapshots in time.
| Fields: ["NormalVelocity", "Temperature", "Salinity"] | ||
| SpatialStats: ["Max", "Min", "Mean", "StdDev"] | ||
| ReductionPeriod: ["1Day", "1Month"] |
There was a problem hiding this comment.
I agree that SnapshotFreq is better than SampleFreq because I assumed that this was indeed the computation interval for temporal stats.
| Fields: ["NormalVelocity", "Temperature", "Salinity"] | ||
| SpatialStats: ["Max", "Min", "Mean", "StdDev"] | ||
| ReductionPeriod: ["1Day", "1Month"] |
There was a problem hiding this comment.
How is the computation interval set (if it is not every time step)?
| - `NormalVelocity_SpatialMean_TimeMean1day` — 1-day time average of the | ||
| spatial mean of NormalVelocity |
There was a problem hiding this comment.
This also answers my question above -- we accumulate every time step for now. Make sense to me.
Add Analysis module design document. Compiled here.
Describes the configurable operator framework for in-situ analysis computation, including:
Checklist