Halide
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  // Below are some concrete methods that build on top of the rest of the AbstractGenerator API.
181  // Note that they are nonvirtual. TODO: would these be better as freestanding methods that
182  // just take AbstractGeneratorPtr as arguments?
183 
184  /** Call generate() and produce a Module for the result.
185  *If function_name is empty, generator_name() will be used for the function. */
186  Module build_module(const std::string &function_name = "");
187 
188  /**
189  * Build a module that is suitable for using for gradient descent calculation in TensorFlow or PyTorch.
190  *
191  * Essentially:
192  * - A new Pipeline is synthesized from the current Generator (according to the rules below)
193  * - The new Pipeline is autoscheduled (if autoscheduling is requested, but it would be odd not to do so)
194  * - The Pipeline is compiled to a Module and returned
195  *
196  * The new Pipeline is adjoint to the original; it has:
197  * - All the same inputs as the original, in the same order
198  * - Followed by one grad-input for each original output
199  * - Followed by one output for each unique pairing of original-output + original-input.
200  * (For the common case of just one original-output, this amounts to being one output for each original-input.)
201  */
202  Module build_gradient_module(const std::string &function_name);
203 
204  /**
205  * JIT the AbstractGenerator into a Callable (using the currently-set
206  * Target) and return it.
207  *
208  * If jit_handlers is not null, set the jitted func's jit_handlers to use a copy of it.
209  *
210  * If jit_externs is not null, use it to set the jitted func's external dependencies.
211  */
212  Callable compile_to_callable(const JITHandlers *jit_handlers = nullptr,
213  const std::map<std::string, JITExtern> *jit_externs = nullptr);
214 
215  /*
216  * Set all the GeneratorParams in the map. This is equivalent to simply calling the
217  * `set_generatorparam_value()` method in a loop over the map, but is quite convenient. */
219 };
220 
221 using AbstractGeneratorPtr = std::unique_ptr<AbstractGenerator>;
222 
223 } // namespace Internal
224 } // namespace Halide
225 
226 #endif
Halide::Callable
Definition: Callable.h:82
Halide::Internal::AbstractGenerator::~AbstractGenerator
virtual ~AbstractGenerator()=default
Halide::Internal::AbstractGenerator::ArgInfo::name
std::string name
Definition: AbstractGenerator.h:68
Halide::Internal::ArgInfoKind
ArgInfoKind
Definition: AbstractGenerator.h:26
Parameter.h
Halide::Internal::ArgInfoKind::Function
@ Function
Halide::Internal::AbstractGenerator::context
virtual GeneratorContext context() const =0
Return the Target and autoscheduler info that this Generator was created with.
Halide::Internal::ArgInfoKind::Scalar
@ Scalar
Halide::Internal::AbstractGenerator
AbstractGenerator is an ABC that defines the API a Generator must provide to work with the existing G...
Definition: AbstractGenerator.h:56
Halide::Internal::AbstractGenerator::bind_input
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 ...
Target.h
Halide::Internal::AbstractGenerator::compile_to_callable
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.
Halide::Internal::AbstractGenerator::set_generatorparam_value
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.
Pipeline.h
Halide::Internal::AbstractGenerator::set_generatorparam_values
void set_generatorparam_values(const GeneratorParamsMap &m)
Halide::Internal::AbstractGenerator::arginfos
virtual std::vector< ArgInfo > arginfos()=0
Return a list of all the ArgInfos for this generator.
Schedule.h
Halide::Internal::AbstractGenerator::ArgInfo::kind
ArgInfoKind kind
Definition: AbstractGenerator.h:70
Halide::Module
A halide module.
Definition: Module.h:138
Halide::Pipeline
A class representing a Halide pipeline.
Definition: Pipeline.h:108
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AbstractGenerator.h:19
Halide::GeneratorParamsMap
std::map< std::string, std::string > GeneratorParamsMap
Definition: AbstractGenerator.h:22
Halide::Internal::AbstractGenerator::ArgInfo::dimensions
int dimensions
Definition: AbstractGenerator.h:73
Halide::LinkageType::Internal
@ Internal
Not visible externally, similar to 'static' linkage in C.
Callable.h
Halide::JITHandlers
A set of custom overrides of runtime functions.
Definition: JITModule.h:35
Func.h
Halide::Buffer
A Halide::Buffer is a named shared reference to a Halide::Runtime::Buffer.
Definition: Argument.h:16
Halide::Internal::ArgInfoDirection
ArgInfoDirection
Definition: AbstractGenerator.h:30
Halide::GeneratorContext
GeneratorContext is a class that is used when using Generators (or Stubs) directly; it is used to all...
Definition: Generator.h:2998
Halide::Internal::ArgInfoDirection::Input
@ Input
Type.h
Expr.h
Halide::Internal::AbstractGenerator::ArgInfo::types
std::vector< Type > types
Definition: AbstractGenerator.h:72
Halide::Internal::AbstractGeneratorPtr
std::unique_ptr< AbstractGenerator > AbstractGeneratorPtr
Definition: AbstractGenerator.h:221
Halide::LoopLevel
A reference to a site in a Halide statement at the top of the body of a particular for loop.
Definition: Schedule.h:176
Halide::Internal::AbstractGenerator::build_module
Module build_module(const std::string &function_name="")
Call generate() and produce a Module for the result.
Halide::Internal::AbstractGenerator::build_gradient_module
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.
Halide::Internal::AbstractGenerator::ArgInfo
ArgInfo is a struct to contain name-and-type information for the inputs and outputs to the Pipeline t...
Definition: AbstractGenerator.h:67
Halide::Internal::AbstractGenerator::build_pipeline
virtual Pipeline build_pipeline()=0
Build and return the Pipeline for this AbstractGenerator.
Halide::Internal::AbstractGenerator::ArgInfo::dir
ArgInfoDirection dir
Definition: AbstractGenerator.h:69
Halide::Internal::AbstractGenerator::name
virtual std::string name()=0
Return the name of this Generator.
Halide::Internal::AbstractGenerator::emit_cpp_stub
virtual bool emit_cpp_stub(const std::string &stub_file_path)=0
Emit a Generator Stub (.stub.h) file to the given path.
Halide::Internal::AbstractGenerator::input_parameter
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.h
Halide::Internal::ArgInfoDirection::Output
@ Output
Halide::Internal::AbstractGenerator::output_func
virtual std::vector< Func > output_func(const std::string &name)=0
Given the name of an output, return the Func(s) for that output.