ExaModelsC: emit the schema + builder ABI for structured recipes - #309
Merged
Conversation
Every instantiate method takes its arguments as a bare vararg that is
only splatted through to child calls. Julia's passthrough heuristic
leaves such varargs unspecialized — harmless under the JIT, but the
map over a core's block tuples then carries a dynamic call that
juliac --trim=safe reports as unresolved (57 verifier errors on the
first multi-argument recipe ever compiled). Annotating every signature
with Vararg{Any,N} forces specialization on the concrete argument
types; behavior is unchanged. ArgumentTest: 158/158.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Recipes whose examples are not a single integer — several values, floats, arrays, tables, or NamedTuples of these, exactly as ExaModel takes them — now compile to the ABI v2 builder surface both consumers already implement: P_schema publishes the flattened field list, P_data_begin / P_set_* / P_data_ready take the values by name, and P_new_from_data reassembles the ExaModel arguments. A NamedTuple example flattens into one schema field per key; bare values are named arg1, arg2, ... by position. Builder models export no P_new — the consumers rely on that disjointness to route a lone integer — and a one-key integer NamedTuple keeps the P_new fast path. Builder storage is generated concretely from the example types (one slot per scalar/array field and per table column), so --trim=safe sees no dynamic containers; examples must be Int64/Float64 exactly, refused otherwise with the reason. Probe failures now surface as ArgumentError naming the model instead of a raw MethodError. Suite: 192/192, including a compiled two-surface library (builder + one-knob in one file), consumption from CNLPModels.jl and cnlpmodels (Python driving the builder with a columnar table), and an Ipopt solve through a builder-instantiated model. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
|
Your PR requires formatting changes to meet the project's style guidelines. Please run: julia --project=@runic -e 'using Pkg; Pkg.add("Runic")'
julia --project=@runic -e "using Runic; exit(Runic.main(ARGS))" -- --fix <files>(or Note: the full diff is omitted because it can exceed GitHub Actions input limits. |
Contributor
Benchmark Results |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Answers the multi-argument question from the other direction:
compile_librarynow compiles recipes whose examples are not a single integer — several values, floats, arrays, tables, or NamedTuples of these, exactly asExaModeltakes them:The emitted surface is the ABI v2 schema + builder both consumers already implement — no consumer changes anywhere.
P_schemapublishes the flattened field list (NamedTuple examples flatten into one field per key, bare values arearg1,arg2, ... by position), the typed setters take values by name, andP_new_from_datareassembles theExaModelarguments. Builder models export noP_new; a one-key integer NamedTuple keeps theP_newfast path — the disjointness the consumers use to route a lone integer.Consumption is the consumers' existing positional spelling, one value per field:
Two commits. The first is in ExaModels proper: every
instantiatemethod took a bare vararg that is only splatted through, which Julia's passthrough heuristic leaves unspecialized — invisible under the JIT, but the first multi-argument AOT compile surfaced it as 57--trim=safeverifier errors. Annotating the signatures withVararg{Any,N}forces specialization; behavior is unchanged (ArgumentTest 158/158).Builder storage is generated concretely from the example types, so
--trim=safesees no dynamic containers; examples must beInt64/Float64exactly (the example's type IS the compiled storage's type), refused otherwise with the reason.Suite: 192/192 — including a compiled two-surface library (builder + one-knob model in one file), consumption from both CNLPModels.jl and
cnlpmodels(Python driving the builder with a columnar table), an Ipopt solve through a builder-instantiated model, and refusal tests for strings, loose numeric types, colliding field names, and shape mismatches.Based on #308 (multi-model) — merge that first; this rides on its
ModelSpecmachinery.🤖 Generated with Claude Code