Halide  20.0.0
Halide compiler and libraries
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 
19 namespace Halide {
20 
21 class GeneratorContext;
22 using GeneratorParamsMap = std::map<std::string, std::string>;
23 
24 namespace Internal {
25 
26 enum class ArgInfoKind { Scalar,
27  Function,
28  Buffer };
29 
30 enum class ArgInfoDirection { Input,
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  */
57 public:
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  */
127  virtual Pipeline build_pipeline() = 0;
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  */
201  virtual bool allow_out_of_order_inputs_and_outputs() const = 0;
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 
244 using 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: Buffer.h:122
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 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 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 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.
virtual std::vector< Parameter > input_parameter(const std::string &name)=0
Given the name of an input, return the Parameter(s) for that input.
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.
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