Halide 19.0.0
Halide compiler and libraries
Loading...
Searching...
No Matches
AbstractGenerator.h
Go to the documentation of this file.
1#ifndef HALIDE_ABSTRACT_GENERATOR_H_
2#define HALIDE_ABSTRACT_GENERATOR_H_
3
4#include <functional>
5#include <map>
6#include <string>
7#include <vector>
8
9#include "Callable.h"
10#include "Expr.h"
11#include "Func.h"
12#include "Module.h"
13#include "Parameter.h"
14#include "Pipeline.h"
15#include "Schedule.h"
16#include "Target.h"
17#include "Type.h"
18
19namespace Halide {
20
22using GeneratorParamsMap = std::map<std::string, std::string>;
23
24namespace Internal {
25
26enum class ArgInfoKind { Scalar,
28 Buffer };
29
31 Output };
32
33/**
34 * AbstractGenerator is an ABC that defines the API a Generator must provide
35 * to work with the existing Generator infrastructure (GenGen, RunGen, execute_generator(),
36 * Generator Stubs). The existing Generator<>-based instances all implement
37 * this API, but any other code that implements this (and uses RegisterGenerator
38 * to register itself) should be indistinguishable from a user perspective.
39 *
40 * An AbstractGenerator is meant to be "single-use"; typically lifetimes will be
41 * something like:
42 * - create an instance (with a specific Target)
43 * - optionally set GeneratorParam values
44 * - optionally re-bind inputs (if using in JIT or Stub modes)
45 * - call build_pipeline()
46 * - optionally call output_func() to get the output(s) (if using in JIT or Stub modes)
47 * - discard the instance
48 *
49 * AbstractGenerators should be fairly cheap to instantiate! Don't try to re-use
50 * one by re-setting inputs and calling build_pipeline() multiple times.
51 *
52 * Note that an AbstractGenerator instance is (generally) stateful in terms of the order
53 * that methods should be called; calling the methods out of order may cause
54 * assert-fails or other undesirable behavior. Read the method notes carefully!
55 */
57public:
58 virtual ~AbstractGenerator() = default;
59
60 /** ArgInfo is a struct to contain name-and-type information for the inputs and outputs to
61 * the Pipeline that build_pipeline() will return.
62 *
63 * Note that this looks rather similar to Halide::Argument, but unfortunately
64 * that is not a good fit here, as it cannot represent Func inputs (only
65 * Buffer and Scalar), nor can it really handle Outputs.
66 */
67 struct ArgInfo {
68 std::string name;
71 // Note that this can have multiple entries for Tuple-valued Inputs or Outputs
72 std::vector<Type> types;
73 int dimensions = 0;
74 };
75
76 /** Return the name of this Generator. (This should always be the name
77 * used to register it.) */
78 virtual std::string name() = 0;
79
80 /** Return the Target and autoscheduler info that this Generator
81 * was created with. Always legal to call on any AbstractGenerator instance,
82 * regardless of what other methods have been called. (All AbstractGenerator instances
83 * are expected to be created with immutable values for these, which can't be
84 * changed for a given instance after creation. Note that Generator<> based subclasses
85 * can customize Target somewhat via init_from_context(); see Generator.h for more info.)
86 *
87 * CALL-AFTER: any
88 * CALL-BEFORE: any
89 */
90 virtual GeneratorContext context() const = 0;
91
92 /** Return a list of all the ArgInfos for this generator. The list will be in the order
93 * that the input and outputs are declared (possibly interleaved).
94 * Any inputs or outputs added by a configure() method will be in the list,
95 * at the end, in the order added.
96 * All input and output names will be unique within a given Generator instance.
97 *
98 * CALL-AFTER: configure()
99 * CALL-BEFORE: any
100 */
101 virtual std::vector<ArgInfo> arginfos() = 0;
102
103 /** Set the value for a specific GeneratorParam for an AbstractGenerator instance.
104 *
105 * Names that aren't known generator names should assert-fail.
106 *
107 * Values that can't be parsed for the specific GeneratorParam (e.g. passing "foo" where
108 * an integer is expected) should assert-fail at some point (either immediately, or when
109 * build_pipeline() is called)
110 *
111 * This can be called multiple times, but only prior to build_pipeline().
112 *
113 * CALL-AFTER: none
114 * CALL-BEFORE: build_pipeline
115 */
116 // @{
117 virtual void set_generatorparam_value(const std::string &name, const std::string &value) = 0;
118 virtual void set_generatorparam_value(const std::string &name, const LoopLevel &loop_level) = 0;
119 // @}
120
121 /** Build and return the Pipeline for this AbstractGenerator. This method should be called
122 * only once per instance.
123 *
124 * CALL-AFTER: set_generatorparam_value, bind_input
125 * CALL-BEFORE: input_parameter, output_func, external_code_map
126 */
128
129 /** Given the name of an input, return the Parameter(s) for that input.
130 * (Most inputs will have exactly one, but inputs that are declared as arrays
131 * will have multiple.)
132 *
133 * CALL-AFTER: build_pipeline
134 * CALL-BEFORE: none
135 */
136 virtual std::vector<Parameter> input_parameter(const std::string &name) = 0;
137
138 /** Given the name of an output, return the Func(s) for that output.
139 *
140 * Most outputs will have exactly one, but outputs that are declared as arrays will have multiple.
141 *
142 * Note that outputs with Tuple values are still just a single Func, though they do get realized
143 * as multiple Buffers.
144 *
145 * Must be called after build_pipeline(), since the output Funcs will be undefined prior to that.
146 *
147 * CALL-AFTER: build_pipeline()
148 * CALL-BEFORE: none
149 */
150 virtual std::vector<Func> output_func(const std::string &name) = 0;
151
152 /** Rebind a specified Input to refer to the given piece of IR, replacing the
153 * default ImageParam / Param in place for that Input. Basic type-checking is
154 * done to ensure that inputs are still sane (e.g. types, dimensions, etc must match expectations).
155 *
156 * CALL-AFTER: set_generatorparam_value
157 * CALL-BEFORE: build_pipeline
158 */
159 // @{
160 virtual void bind_input(const std::string &name, const std::vector<Parameter> &v) = 0;
161 virtual void bind_input(const std::string &name, const std::vector<Func> &v) = 0;
162 virtual void bind_input(const std::string &name, const std::vector<Expr> &v) = 0;
163 // @}
164
165 /** Emit a Generator Stub (.stub.h) file to the given path. Not all Generators support this.
166 *
167 * If you call this method, you should not call any other AbstractGenerator methods
168 * on this instance, before or after this call.
169 *
170 * If the Generator is capable of emitting a Stub, do so and return true. (Errors
171 * during stub emission should assert-fail rather than returning false.)
172 *
173 * If the Generator is not capable of emitting a Stub, do nothing and return false.
174 *
175 * CALL-AFTER: none
176 * CALL-BEFORE: none
177 */
178 virtual bool emit_cpp_stub(const std::string &stub_file_path) = 0;
179
180 /** Emit a Serialized Halide Pipeline (.hlpipe) file to the given path. Not all Generators support this.
181 *
182 * If you call this method, you should not call any other AbstractGenerator methods
183 * on this instance, before or after this call.
184 *
185 * If the Generator is capable of emitting an hlpipe, do so and return true. (Errors
186 * during hlpipe emission should assert-fail rather than returning false.)
187 *
188 * If the Generator is not capable of emitting an hlpipe, do nothing and return false.
189 *
190 * CALL-AFTER: none
191 * CALL-BEFORE: none
192 */
193 virtual bool emit_hlpipe(const std::string &hlpipe_file_path) = 0;
194
195 /** By default, a Generator must declare all Inputs before all Outputs.
196 * In some unusual situations (e.g. metaprogramming situations), it's
197 * desirable to allow them to be declared out-of-order and put the onus
198 * of a non-obvious call order on the coder; a Generator may override this
199 * to return 'true' to allow this behavior.
200 */
202
203 // Below are some concrete methods that build on top of the rest of the AbstractGenerator API.
204 // Note that they are nonvirtual. TODO: would these be better as freestanding methods that
205 // just take AbstractGeneratorPtr as arguments?
206
207 /** Call generate() and produce a Module for the result.
208 *If function_name is empty, generator_name() will be used for the function. */
209 Module build_module(const std::string &function_name = "");
210
211 /**
212 * Build a module that is suitable for using for gradient descent calculation in TensorFlow or PyTorch.
213 *
214 * Essentially:
215 * - A new Pipeline is synthesized from the current Generator (according to the rules below)
216 * - The new Pipeline is autoscheduled (if autoscheduling is requested, but it would be odd not to do so)
217 * - The Pipeline is compiled to a Module and returned
218 *
219 * The new Pipeline is adjoint to the original; it has:
220 * - All the same inputs as the original, in the same order
221 * - Followed by one grad-input for each original output
222 * - Followed by one output for each unique pairing of original-output + original-input.
223 * (For the common case of just one original-output, this amounts to being one output for each original-input.)
224 */
225 Module build_gradient_module(const std::string &function_name);
226
227 /**
228 * JIT the AbstractGenerator into a Callable (using the currently-set
229 * Target) and return it.
230 *
231 * If jit_handlers is not null, set the jitted func's jit_handlers to use a copy of it.
232 *
233 * If jit_externs is not null, use it to set the jitted func's external dependencies.
234 */
235 Callable compile_to_callable(const JITHandlers *jit_handlers = nullptr,
236 const std::map<std::string, JITExtern> *jit_externs = nullptr);
237
238 /*
239 * Set all the GeneratorParams in the map. This is equivalent to simply calling the
240 * `set_generatorparam_value()` method in a loop over the map, but is quite convenient. */
242};
243
244using AbstractGeneratorPtr = std::unique_ptr<AbstractGenerator>;
245
246} // namespace Internal
247} // namespace Halide
248
249#endif
Defines the front-end class representing a jitted, callable Halide pipeline.
Base classes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt)
Defines Func - the front-end handle on a halide function, and related classes.
Defines Module, an IR container that fully describes a Halide program.
Defines the internal representation of parameters to halide piplines.
Defines the front-end class representing an entire Halide imaging pipeline.
Defines the internal representation of the schedule for a function.
Defines the structure that describes a Halide target.
Defines halide types.
A Halide::Buffer is a named shared reference to a Halide::Runtime::Buffer.
Definition RDom.h:21
GeneratorContext is a class that is used when using Generators (or Stubs) directly; it is used to all...
Definition Generator.h:3007
AbstractGenerator is an ABC that defines the API a Generator must provide to work with the existing G...
virtual std::vector< ArgInfo > arginfos()=0
Return a list of all the ArgInfos for this generator.
virtual bool emit_cpp_stub(const std::string &stub_file_path)=0
Emit a Generator Stub (.stub.h) file to the given path.
void set_generatorparam_values(const GeneratorParamsMap &m)
virtual void set_generatorparam_value(const std::string &name, const std::string &value)=0
Set the value for a specific GeneratorParam for an AbstractGenerator instance.
virtual bool emit_hlpipe(const std::string &hlpipe_file_path)=0
Emit a Serialized Halide Pipeline (.hlpipe) file to the given path.
virtual void bind_input(const std::string &name, const std::vector< Func > &v)=0
virtual bool allow_out_of_order_inputs_and_outputs() const =0
By default, a Generator must declare all Inputs before all Outputs.
virtual void bind_input(const std::string &name, const std::vector< Parameter > &v)=0
Rebind a specified Input to refer to the given piece of IR, replacing the default ImageParam / Param ...
Callable compile_to_callable(const JITHandlers *jit_handlers=nullptr, const std::map< std::string, JITExtern > *jit_externs=nullptr)
JIT the AbstractGenerator into a Callable (using the currently-set Target) and return it.
virtual std::vector< Func > output_func(const std::string &name)=0
Given the name of an output, return the Func(s) for that output.
virtual void set_generatorparam_value(const std::string &name, const LoopLevel &loop_level)=0
virtual void bind_input(const std::string &name, const std::vector< Expr > &v)=0
virtual Pipeline build_pipeline()=0
Build and return the Pipeline for this AbstractGenerator.
Module build_gradient_module(const std::string &function_name)
Build a module that is suitable for using for gradient descent calculation in TensorFlow or PyTorch.
virtual std::string name()=0
Return the name of this Generator.
virtual GeneratorContext context() const =0
Return the Target and autoscheduler info that this Generator was created with.
Module build_module(const std::string &function_name="")
Call generate() and produce a Module for the result.
virtual std::vector< Parameter > input_parameter(const std::string &name)=0
Given the name of an input, return the Parameter(s) for that input.
A reference to a site in a Halide statement at the top of the body of a particular for loop.
Definition Schedule.h:203
A halide module.
Definition Module.h:142
A class representing a Halide pipeline.
Definition Pipeline.h:107
std::unique_ptr< AbstractGenerator > AbstractGeneratorPtr
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
std::map< std::string, std::string > GeneratorParamsMap
ArgInfo is a struct to contain name-and-type information for the inputs and outputs to the Pipeline t...
A set of custom overrides of runtime functions.
Definition JITModule.h:35