Halide
Generator.h File Reference
#include <algorithm>
#include <functional>
#include <iterator>
#include <limits>
#include <memory>
#include <mutex>
#include <set>
#include <sstream>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include "AbstractGenerator.h"
#include "Func.h"
#include "ImageParam.h"
#include "Introspection.h"
#include "ObjectInstanceRegistry.h"
#include "Target.h"

Go to the source code of this file.

Classes

class  Halide::Internal::GeneratorFactoryProvider
 GeneratorFactoryProvider provides a way to customize the Generators that are visible to generate_filter_main (which otherwise would just look at the global registry of C++ Generators). More...
 
struct  Halide::Internal::cond< B, T >
 
struct  Halide::Internal::select_type< First, Rest >
 
struct  Halide::Internal::select_type< First >
 
class  Halide::Internal::GeneratorParamBase
 
struct  Halide::Internal::Convert< FROM, TO >
 
class  Halide::Internal::GeneratorParamImpl< T >
 
class  Halide::Internal::GeneratorParam_Target< T >
 
class  Halide::Internal::GeneratorParam_AutoSchedulerParams
 
class  Halide::Internal::GeneratorParam_LoopLevel
 
class  Halide::Internal::GeneratorParam_Arithmetic< T >
 
class  Halide::Internal::GeneratorParam_Bool< T >
 
class  Halide::Internal::GeneratorParam_Enum< T >
 
class  Halide::Internal::GeneratorParam_Type< T >
 
class  Halide::Internal::GeneratorParam_String< T >
 
class  Halide::GeneratorParam< T >
 GeneratorParam is a templated class that can be used to modify the behavior of the Generator at code-generation time. More...
 
class  Halide::Internal::GeneratorInput_Buffer< T >
 
class  Halide::Internal::StubInputBuffer< T, Dims >
 StubInputBuffer is the placeholder that a Stub uses when it requires a Buffer for an input (rather than merely a Func or Expr). More...
 
class  Halide::Internal::StubOutputBufferBase
 
class  Halide::Internal::StubOutputBuffer< T >
 StubOutputBuffer is the placeholder that a Stub uses when it requires a Buffer for an output (rather than merely a Func). More...
 
class  Halide::Internal::StubInput
 
class  Halide::Internal::GIOBase
 GIOBase is the base class for all GeneratorInput<> and GeneratorOutput<> instantiations; it is not part of the public API and should never be used directly by user code. More...
 
class  Halide::Internal::GeneratorInputBase
 
class  Halide::Internal::GeneratorInputImpl< T, ValueType >
 
class  Halide::Internal::GeneratorInput_Buffer< T >
 
class  Halide::Internal::GeneratorInput_Func< T >
 
class  Halide::Internal::GeneratorInput_DynamicScalar< T >
 
class  Halide::Internal::GeneratorInput_Scalar< T >
 
class  Halide::Internal::GeneratorInput_Arithmetic< T >
 
struct  Halide::Internal::type_sink< typename >
 
struct  Halide::Internal::has_static_halide_type_method< T2, typename >
 
struct  Halide::Internal::has_static_halide_type_method< T2, typename type_sink< decltype(T2::static_halide_type())>::type >
 
class  Halide::GeneratorInput< T >
 
class  Halide::Internal::GeneratorOutputBase
 
class  Halide::Internal::GeneratorOutputImpl< T >
 
class  Halide::Internal::GeneratorOutput_Buffer< T >
 
class  Halide::Internal::GeneratorOutput_Func< T >
 
class  Halide::Internal::GeneratorOutput_Arithmetic< T >
 
class  Halide::GeneratorOutput< T >
 
class  Halide::Internal::GeneratorParam_Synthetic< T >
 
class  Halide::GeneratorContext
 GeneratorContext is a class that is used when using Generators (or Stubs) directly; it is used to allow the outer context (typically, either a Generator or "top-level" code) to specify certain information to the inner context to ensure that inner and outer Generators are compiled in a compatible way. More...
 
class  Halide::NamesInterface
 
struct  Halide::Internal::NoRealizations< Args >
 
struct  Halide::Internal::NoRealizations<>
 
struct  Halide::Internal::NoRealizations< T, Args... >
 
class  Halide::Internal::GeneratorParamInfo
 
class  Halide::Internal::GeneratorBase
 
class  Halide::Internal::GeneratorRegistry
 
class  Halide::Generator< T >
 
class  Halide::Internal::RegisterGenerator
 
struct  Halide::Internal::ExecuteGeneratorArgs
 ExecuteGeneratorArgs is the set of arguments to execute_generator(). More...
 

Namespaces

 Halide
 This file defines the class FunctionDAG, which is our representation of a Halide pipeline, and contains methods to using Halide's bounds tools to query properties of it.
 
 Halide::Internal
 
 Halide::Internal::GeneratorMinMax
 
 halide_register_generator
 

Macros

#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE)   virtual void set(const TYPE &new_value) = 0;
 
#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE)
 
#define HALIDE_FORWARD_METHOD(Class, Method)
 
#define HALIDE_FORWARD_METHOD_CONST(Class, Method)
 
#define _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)
 
#define _HALIDE_REGISTER_GENERATOR2(GEN_CLASS_NAME, GEN_REGISTRY_NAME)   _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, GEN_REGISTRY_NAME)
 
#define _HALIDE_REGISTER_GENERATOR3(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)   _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)
 
#define __HALIDE_REGISTER_ARGCOUNT_IMPL(_1, _2, _3, COUNT, ...)   COUNT
 
#define _HALIDE_REGISTER_ARGCOUNT_IMPL(ARGS)   __HALIDE_REGISTER_ARGCOUNT_IMPL ARGS
 
#define _HALIDE_REGISTER_ARGCOUNT(...)   _HALIDE_REGISTER_ARGCOUNT_IMPL((__VA_ARGS__, 3, 2, 1, 0))
 
#define ___HALIDE_REGISTER_CHOOSER(COUNT)   _HALIDE_REGISTER_GENERATOR##COUNT
 
#define __HALIDE_REGISTER_CHOOSER(COUNT)   ___HALIDE_REGISTER_CHOOSER(COUNT)
 
#define _HALIDE_REGISTER_CHOOSER(COUNT)   __HALIDE_REGISTER_CHOOSER(COUNT)
 
#define _HALIDE_REGISTER_GENERATOR_PASTE(A, B)   A B
 
#define HALIDE_REGISTER_GENERATOR(...)   _HALIDE_REGISTER_GENERATOR_PASTE(_HALIDE_REGISTER_CHOOSER(_HALIDE_REGISTER_ARGCOUNT(__VA_ARGS__)), (__VA_ARGS__))
 
#define HALIDE_REGISTER_GENERATOR_ALIAS(GEN_REGISTRY_NAME, ORIGINAL_REGISTRY_NAME, ...)
 
#define HALIDE_GENERATOR_PYSTUB(GEN_REGISTRY_NAME, MODULE_NAME)
 

Typedefs

template<typename T >
using Halide::Internal::GeneratorParamImplBase = typename select_type< cond< std::is_same< T, Target >::value, GeneratorParam_Target< T > >, cond< std::is_same< T, LoopLevel >::value, GeneratorParam_LoopLevel >, cond< std::is_same< T, std::string >::value, GeneratorParam_String< T > >, cond< std::is_same< T, Type >::value, GeneratorParam_Type< T > >, cond< std::is_same< T, bool >::value, GeneratorParam_Bool< T > >, cond< std::is_arithmetic< T >::value, GeneratorParam_Arithmetic< T > >, cond< std::is_enum< T >::value, GeneratorParam_Enum< T > >>::type
 
template<typename T , typename TBase = typename std::remove_all_extents<T>::type>
using Halide::Internal::GeneratorInputImplBase = typename select_type< cond< has_static_halide_type_method< TBase >::value, GeneratorInput_Buffer< T > >, cond< std::is_same< TBase, Func >::value, GeneratorInput_Func< T > >, cond< std::is_arithmetic< TBase >::value, GeneratorInput_Arithmetic< T > >, cond< std::is_scalar< TBase >::value, GeneratorInput_Scalar< T > >, cond< std::is_same< TBase, Expr >::value, GeneratorInput_DynamicScalar< T > >>::type
 
template<typename T , typename TBase = typename std::remove_all_extents<T>::type>
using Halide::Internal::GeneratorOutputImplBase = typename select_type< cond< has_static_halide_type_method< TBase >::value, GeneratorOutput_Buffer< T > >, cond< std::is_same< TBase, Func >::value, GeneratorOutput_Func< T > >, cond< std::is_arithmetic< TBase >::value, GeneratorOutput_Arithmetic< T > >>::type
 
using Halide::Internal::GeneratorFactory = std::function< AbstractGeneratorPtr(const GeneratorContext &context)>
 

Enumerations

enum  Halide::Internal::SyntheticParamType { Halide::Internal::SyntheticParamType::Type, Halide::Internal::SyntheticParamType::Dim, Halide::Internal::SyntheticParamType::ArraySize }
 

Functions

void Halide::Internal::generator_test ()
 
std::vector< Expr > Halide::Internal::parameter_constraints (const Parameter &p)
 
template<typename T >
HALIDE_NO_USER_CODE_INLINE std::string Halide::Internal::enum_to_string (const std::map< std::string, T > &enum_map, const T &t)
 
template<typename T >
Halide::Internal::enum_from_string (const std::map< std::string, T > &enum_map, const std::string &s)
 
const std::map< std::string, Halide::Type > & Halide::Internal::get_halide_type_enum_map ()
 
std::string Halide::Internal::halide_type_to_enum_string (const Type &t)
 
std::string Halide::Internal::halide_type_to_c_source (const Type &t)
 
std::string Halide::Internal::halide_type_to_c_type (const Type &t)
 
const GeneratorFactoryProvider & Halide::Internal::get_registered_generators ()
 Return a GeneratorFactoryProvider that knows about all the currently-registered C++ Generators. More...
 
int Halide::Internal::generate_filter_main (int argc, char **argv)
 generate_filter_main() is a convenient wrapper for GeneratorRegistry::create() + compile_to_files(); it can be trivially wrapped by a "real" main() to produce a command-line utility for ahead-of-time filter compilation. More...
 
int Halide::Internal::generate_filter_main (int argc, char **argv, const GeneratorFactoryProvider &generator_factory_provider)
 This overload of generate_filter_main lets you provide your own provider for how to enumerate and/or create the generators based on registration name; this is useful if you want to re-use the 'main' logic but avoid the global Generator registry (e.g. More...
 
template<typename Other , typename T >
auto Halide::operator+ (const Other &a, const GeneratorParam< T > &b) -> decltype(a+(T) b)
 Addition between GeneratorParam<T> and any type that supports operator+ with T. More...
 
template<typename Other , typename T >
auto Halide::operator+ (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a+b)
 
template<typename Other , typename T >
auto Halide::operator- (const Other &a, const GeneratorParam< T > &b) -> decltype(a -(T) b)
 Subtraction between GeneratorParam<T> and any type that supports operator- with T. More...
 
template<typename Other , typename T >
auto Halide::operator- (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a - b)
 
template<typename Other , typename T >
auto Halide::operator* (const Other &a, const GeneratorParam< T > &b) -> decltype(a *(T) b)
 Multiplication between GeneratorParam<T> and any type that supports operator* with T. More...
 
template<typename Other , typename T >
auto Halide::operator* (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a *b)
 
template<typename Other , typename T >
auto Halide::operator/ (const Other &a, const GeneratorParam< T > &b) -> decltype(a/(T) b)
 Division between GeneratorParam<T> and any type that supports operator/ with T. More...
 
template<typename Other , typename T >
auto Halide::operator/ (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a/b)
 
template<typename Other , typename T >
auto Halide::operator% (const Other &a, const GeneratorParam< T > &b) -> decltype(a %(T) b)
 Modulo between GeneratorParam<T> and any type that supports operator% with T. More...
 
template<typename Other , typename T >
auto Halide::operator% (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a % b)
 
template<typename Other , typename T >
auto Halide::operator> (const Other &a, const GeneratorParam< T > &b) -> decltype(a >(T) b)
 Greater than comparison between GeneratorParam<T> and any type that supports operator> with T. More...
 
template<typename Other , typename T >
auto Halide::operator> (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a > b)
 
template<typename Other , typename T >
auto Halide::operator< (const Other &a, const GeneratorParam< T > &b) -> decltype(a<(T) b)
 Less than comparison between GeneratorParam<T> and any type that supports operator< with T. More...
 
template<typename Other , typename T >
auto Halide::operator< (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a< b)
 
template<typename Other , typename T >
auto Halide::operator>= (const Other &a, const GeneratorParam< T > &b) -> decltype(a >=(T) b)
 Greater than or equal comparison between GeneratorParam<T> and any type that supports operator>= with T. More...
 
template<typename Other , typename T >
auto Halide::operator>= (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a >=b)
 
template<typename Other , typename T >
auto Halide::operator<= (const Other &a, const GeneratorParam< T > &b) -> decltype(a<=(T) b)
 Less than or equal comparison between GeneratorParam<T> and any type that supports operator<= with T. More...
 
template<typename Other , typename T >
auto Halide::operator<= (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a<=b)
 
template<typename Other , typename T >
auto Halide::operator== (const Other &a, const GeneratorParam< T > &b) -> decltype(a==(T) b)
 Equality comparison between GeneratorParam<T> and any type that supports operator== with T. More...
 
template<typename Other , typename T >
auto Halide::operator== (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a==b)
 
template<typename Other , typename T >
auto Halide::operator!= (const Other &a, const GeneratorParam< T > &b) -> decltype(a !=(T) b)
 Inequality comparison between between GeneratorParam<T> and any type that supports operator!= with T. More...
 
template<typename Other , typename T >
auto Halide::operator!= (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a !=b)
 
template<typename Other , typename T >
auto Halide::operator&& (const Other &a, const GeneratorParam< T > &b) -> decltype(a &&(T) b)
 Logical and between between GeneratorParam<T> and any type that supports operator&& with T. More...
 
template<typename Other , typename T >
auto Halide::operator&& (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a &&b)
 
template<typename T >
auto Halide::operator&& (const GeneratorParam< T > &a, const GeneratorParam< T > &b) -> decltype((T) a &&(T) b)
 
template<typename Other , typename T >
auto Halide::operator|| (const Other &a, const GeneratorParam< T > &b) -> decltype(a||(T) b)
 Logical or between between GeneratorParam<T> and any type that supports operator|| with T. More...
 
template<typename Other , typename T >
auto Halide::operator|| (const GeneratorParam< T > &a, const Other &b) -> decltype((T) a||b)
 
template<typename T >
auto Halide::operator|| (const GeneratorParam< T > &a, const GeneratorParam< T > &b) -> decltype((T) a||(T) b)
 
template<typename Other , typename T >
auto Halide::Internal::GeneratorMinMax::min_forward (const Other &a, const GeneratorParam< T > &b) -> decltype(min(a,(T) b))
 
template<typename Other , typename T >
auto Halide::Internal::GeneratorMinMax::min_forward (const GeneratorParam< T > &a, const Other &b) -> decltype(min((T) a, b))
 
template<typename Other , typename T >
auto Halide::Internal::GeneratorMinMax::max_forward (const Other &a, const GeneratorParam< T > &b) -> decltype(max(a,(T) b))
 
template<typename Other , typename T >
auto Halide::Internal::GeneratorMinMax::max_forward (const GeneratorParam< T > &a, const Other &b) -> decltype(max((T) a, b))
 
template<typename Other , typename T >
auto Halide::min (const Other &a, const GeneratorParam< T > &b) -> decltype(Internal::GeneratorMinMax::min_forward(a, b))
 Compute minimum between GeneratorParam<T> and any type that supports min with T. More...
 
template<typename Other , typename T >
auto Halide::min (const GeneratorParam< T > &a, const Other &b) -> decltype(Internal::GeneratorMinMax::min_forward(a, b))
 
template<typename Other , typename T >
auto Halide::max (const Other &a, const GeneratorParam< T > &b) -> decltype(Internal::GeneratorMinMax::max_forward(a, b))
 Compute the maximum value between GeneratorParam<T> and any type that supports max with T. More...
 
template<typename Other , typename T >
auto Halide::max (const GeneratorParam< T > &a, const Other &b) -> decltype(Internal::GeneratorMinMax::max_forward(a, b))
 
template<typename T >
auto Halide::operator! (const GeneratorParam< T > &a) -> decltype(!(T) a)
 Not operator for GeneratorParam. More...
 
template<typename T >
Halide::Internal::parse_scalar (const std::string &value)
 
std::vector< Type > Halide::Internal::parse_halide_type_list (const std::string &types)
 
void Halide::Internal::execute_generator (const ExecuteGeneratorArgs &args)
 Execute a Generator for AOT compilation – this provides the implementation of the command-line Generator interface generate_filter_main(), but with a structured API that is more suitable for calling directly from code (vs command line). More...
 
Callable Halide::create_callable_from_generator (const GeneratorContext &context, const std::string &name, const GeneratorParamsMap &generator_params={})
 Create a Generator from the currently-registered Generators, use it to create a Callable. More...
 
Callable Halide::create_callable_from_generator (const Target &target, const std::string &name, const GeneratorParamsMap &generator_params={})
 

Detailed Description

Generator is a class used to encapsulate the building of Funcs in user pipelines. A Generator is agnostic to JIT vs AOT compilation; it can be used for either purpose, but is especially convenient to use for AOT compilation.

A Generator explicitly declares the Inputs and Outputs associated for a given pipeline, and (optionally) separates the code for constructing the outputs from the code from scheduling them. For instance:

class Blur : public Generator<Blur> {
public:
Input<Func> input{"input", UInt(16), 2};
Output<Func> output{"output", UInt(16), 2};
void generate() {
blur_x(x, y) = (input(x, y) + input(x+1, y) + input(x+2, y))/3;
blur_y(x, y) = (blur_x(x, y) + blur_x(x, y+1) + blur_x(x, y+2))/3;
output(x, y) = blur(x, y);
}
void schedule() {
blur_y.split(y, y, yi, 8).parallel(y).vectorize(x, 8);
blur_x.store_at(blur_y, y).compute_at(blur_y, yi).vectorize(x, 8);
}
private:
Var x, y, xi, yi;
Func blur_x, blur_y;
};

Halide can compile a Generator into the correct pipeline by introspecting these values and constructing an appropriate signature based on them.

A Generator provides implementations of two methods:

  • generate(), which must fill in all Output Func(s); it may optionally also do scheduling if no schedule() method is present.
  • schedule(), which (if present) should contain all scheduling code.

Inputs can be any C++ scalar type:

Input<float> radius{"radius"};
Input<int32_t> increment{"increment"};

An Input<Func> is (essentially) like an ImageParam, except that it may (or may not) not be backed by an actual buffer, and thus has no defined extents.

Input<Func> input{"input", Float(32), 2};

You can optionally make the type and/or dimensions of Input<Func> unspecified, in which case the value is simply inferred from the actual Funcs passed to them. Of course, if you specify an explicit Type or Dimension, we still require the input Func to match, or a compilation error results.

Input<Func> input{ "input", 3 }; // require 3-dimensional Func,
// but leave Type unspecified

A Generator must explicitly list the output(s) it produces:

Output<Func> output{"output", Float(32), 2};

You can specify an output that returns a Tuple by specifying a list of Types:

class Tupler : Generator<Tupler> {
Input<Func> input{"input", Int(32), 2};
Output<Func> output{"output", {Float(32), UInt(8)}, 2};
void generate() {
Var x, y;
Expr a = cast<float>(input(x, y));
Expr b = cast<uint8_t>(input(x, y));
output(x, y) = Tuple(a, b);
}
};

You can also specify Output<X> for any scalar type (except for Handle types); this is merely syntactic sugar on top of a zero-dimensional Func, but can be quite handy, especially when used with multiple outputs:

Output<float> sum{"sum"}; // equivalent to Output<Func> {"sum", Float(32), 0}

As with Input<Func>, you can optionally make the type and/or dimensions of an Output<Func> unspecified; any unspecified types must be resolved via an implicit GeneratorParam in order to use top-level compilation.

You can also declare an array of Input or Output, by using an array type as the type parameter:

// Takes exactly 3 images and outputs exactly 3 sums.
class SumRowsAndColumns : Generator<SumRowsAndColumns> {
Input<Func[3]> inputs{"inputs", Float(32), 2};
Input<int32_t[2]> extents{"extents"};
Output<Func[3]> sums{"sums", Float(32), 1};
void generate() {
assert(inputs.size() == sums.size());
// assume all inputs are same extent
Expr width = extent[0];
Expr height = extent[1];
for (size_t i = 0; i < inputs.size(); ++i) {
RDom r(0, width, 0, height);
sums[i]() = 0.f;
sums[i]() += inputs[i](r.x, r.y);
}
}
};

You can also leave array size unspecified, with some caveats:

  • For ahead-of-time compilation, Inputs must have a concrete size specified via a GeneratorParam at build time (e.g., pyramid.size=3)
  • For JIT compilation via a Stub, Inputs array sizes will be inferred from the vector passed.
  • For ahead-of-time compilation, Outputs may specify a concrete size via a GeneratorParam at build time (e.g., pyramid.size=3), or the size can be specified via a resize() method.
class Pyramid : public Generator<Pyramid> {
public:
GeneratorParam<int32_t> levels{"levels", 10};
Input<Func> input{ "input", Float(32), 2 };
Output<Func[]> pyramid{ "pyramid", Float(32), 2 };
void generate() {
pyramid.resize(levels);
pyramid[0](x, y) = input(x, y);
for (int i = 1; i < pyramid.size(); i++) {
pyramid[i](x, y) = (pyramid[i-1](2*x, 2*y) +
pyramid[i-1](2*x+1, 2*y) +
pyramid[i-1](2*x, 2*y+1) +
pyramid[i-1](2*x+1, 2*y+1))/4;
}
}
};

A Generator can also be customized via compile-time parameters (GeneratorParams), which affect code generation.

GeneratorParams, Inputs, and Outputs are (by convention) always public and always declared at the top of the Generator class, in the order

GeneratorParam(s)
Input<Func>(s)
Input<non-Func>(s)
Output<Func>(s)

Note that the Inputs and Outputs will appear in the C function call in the order they are declared. All Input<Func> and Output<Func> are represented as halide_buffer_t; all other Input<> are the appropriate C++ scalar type. (GeneratorParams are always referenced by name, not position, so their order is irrelevant.)

All Inputs and Outputs must have explicit names, and all such names must match the regex [A-Za-z][A-Za-z_0-9]* (i.e., essentially a C/C++ variable name, with some extra restrictions on underscore use). By convention, the name should match the member-variable name.

You can dynamically add Inputs and Outputs to your Generator via adding a configure() method; if present, it will be called before generate(). It can examine GeneratorParams but it may not examine predeclared Inputs or Outputs; the only thing it should do is call add_input<>() and/or add_output<>(), or call set_type()/set_dimensions()/set_array_size() on an Input or Output with an unspecified type. Added inputs will be appended (in order) after predeclared Inputs but before any Outputs; added outputs will be appended after predeclared Outputs.

Note that the pointers returned by add_input() and add_output() are owned by the Generator and will remain valid for the Generator's lifetime; user code should not attempt to delete or free them.

class MultiSum : public Generator<MultiSum> {
public:
GeneratorParam<int32_t> input_count{"input_count", 10};
Output<Func> output{ "output", Float(32), 2 };
void configure() {
for (int i = 0; i < input_count; ++i) {
extra_inputs.push_back(
add_input<Func>("input_" + std::to_string(i), Float(32), 2);
}
}
void generate() {
Expr sum = 0.f;
for (int i = 0; i < input_count; ++i) {
sum += (*extra_inputs)[i](x, y);
}
output(x, y) = sum;
}
private:
std::vector<Input<Func>* extra_inputs;
};

All Generators have two GeneratorParams that are implicitly provided by the base class:

GeneratorParam<Target> target{"target", Target()};
GeneratorParam<AutoschedulerParams> autoscheduler{"autoscheduler", {}}
  • 'target' is the Halide::Target for which the Generator is producing code. It is read-only during the Generator's lifetime, and must not be modified; its value should always be filled in by the calling code: either the Halide build system (for ahead-of-time compilation), or ordinary C++ code (for JIT compilation).
  • 'autoscheduler' is a string-to-string map that is used to indicates whether and how an auto-scheduler should be run for this Generator:
    • if empty, the Generator should schedule its Funcs as it sees fit; no autoscheduler will be run.
    • if the 'name' key is set, it should be one of the known autoschedulers provided with this release of Halide, which will be used to schedule the Funcs in the Generator. In this case, the Generator should only provide estimate()s for its Funcs, and not call any other scheduling methods.
    • Other keys may be specified in the params, on a per-autoscheduler basis, to optimize or enhance the automatically-generated schedule. See documentation for each autoscheduler for options.

Generators are added to a global registry to simplify AOT build mechanics; this is done by simply using the HALIDE_REGISTER_GENERATOR macro at global scope:

HALIDE_REGISTER_GENERATOR(ExampleGen, jit_example)

The registered name of the Generator is provided must match the same rules as Input names, above.

Note that the class name of the generated Stub class will match the registered name by default; if you want to vary it (typically, to include namespaces), you can add it as an optional third argument:

HALIDE_REGISTER_GENERATOR(ExampleGen, jit_example, SomeNamespace::JitExampleStub)

Note that a Generator is always executed with a specific Target assigned to it, that you can access via the get_target() method. (You should not use the global get_target_from_environment(), etc. methods provided in Target.h)

(Note that there are older variations of Generator that differ from what's documented above; these are still supported but not described here. See https://github.com/halide/Halide/wiki/Old-Generator-Documentation for more information.)

Definition in file Generator.h.

Macro Definition Documentation

◆ HALIDE_GENERATOR_PARAM_TYPED_SETTER [1/2]

#define HALIDE_GENERATOR_PARAM_TYPED_SETTER (   TYPE)    virtual void set(const TYPE &new_value) = 0;

Definition at line 525 of file Generator.h.

◆ HALIDE_GENERATOR_PARAM_TYPED_SETTER [2/2]

#define HALIDE_GENERATOR_PARAM_TYPED_SETTER (   TYPE)
Value:
void set(const TYPE &new_value) override { \
typed_setter_impl<TYPE>(new_value, #TYPE); \
}

Definition at line 525 of file Generator.h.

◆ HALIDE_FORWARD_METHOD

#define HALIDE_FORWARD_METHOD (   Class,
  Method 
)
Value:
template<typename... Args> \
inline auto Method(Args &&...args)->typename std::remove_reference<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))>::type { \
return this->template as<Class>().Method(std::forward<Args>(args)...); \
}

Definition at line 1647 of file Generator.h.

◆ HALIDE_FORWARD_METHOD_CONST

#define HALIDE_FORWARD_METHOD_CONST (   Class,
  Method 
)
Value:
template<typename... Args> \
inline auto Method(Args &&...args) const-> \
typename std::remove_reference<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))>::type { \
this->check_gio_access(); \
return this->template as<Class>().Method(std::forward<Args>(args)...); \
}

Definition at line 1653 of file Generator.h.

◆ _HALIDE_REGISTER_GENERATOR_IMPL

#define _HALIDE_REGISTER_GENERATOR_IMPL (   GEN_CLASS_NAME,
  GEN_REGISTRY_NAME,
  FULLY_QUALIFIED_STUB_NAME 
)
Value:
struct halide_global_ns; \
namespace GEN_REGISTRY_NAME##_ns { \
std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context) { \
using GenType = std::remove_pointer<decltype(new GEN_CLASS_NAME)>::type; /* NOLINT(bugprone-macro-parentheses) */ \
return GenType::create(context, #GEN_REGISTRY_NAME, #FULLY_QUALIFIED_STUB_NAME); \
} \
} \
static auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
} \
static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
"HALIDE_REGISTER_GENERATOR must be used at global scope");

Definition at line 3980 of file Generator.h.

◆ _HALIDE_REGISTER_GENERATOR2

#define _HALIDE_REGISTER_GENERATOR2 (   GEN_CLASS_NAME,
  GEN_REGISTRY_NAME 
)    _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, GEN_REGISTRY_NAME)

Definition at line 3995 of file Generator.h.

◆ _HALIDE_REGISTER_GENERATOR3

#define _HALIDE_REGISTER_GENERATOR3 (   GEN_CLASS_NAME,
  GEN_REGISTRY_NAME,
  FULLY_QUALIFIED_STUB_NAME 
)    _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)

Definition at line 3998 of file Generator.h.

◆ __HALIDE_REGISTER_ARGCOUNT_IMPL

#define __HALIDE_REGISTER_ARGCOUNT_IMPL (   _1,
  _2,
  _3,
  COUNT,
  ... 
)    COUNT

Definition at line 4004 of file Generator.h.

◆ _HALIDE_REGISTER_ARGCOUNT_IMPL

#define _HALIDE_REGISTER_ARGCOUNT_IMPL (   ARGS)    __HALIDE_REGISTER_ARGCOUNT_IMPL ARGS

Definition at line 4007 of file Generator.h.

◆ _HALIDE_REGISTER_ARGCOUNT

#define _HALIDE_REGISTER_ARGCOUNT (   ...)    _HALIDE_REGISTER_ARGCOUNT_IMPL((__VA_ARGS__, 3, 2, 1, 0))

Definition at line 4010 of file Generator.h.

◆ ___HALIDE_REGISTER_CHOOSER

#define ___HALIDE_REGISTER_CHOOSER (   COUNT)    _HALIDE_REGISTER_GENERATOR##COUNT

Definition at line 4013 of file Generator.h.

◆ __HALIDE_REGISTER_CHOOSER

#define __HALIDE_REGISTER_CHOOSER (   COUNT)    ___HALIDE_REGISTER_CHOOSER(COUNT)

Definition at line 4016 of file Generator.h.

◆ _HALIDE_REGISTER_CHOOSER

#define _HALIDE_REGISTER_CHOOSER (   COUNT)    __HALIDE_REGISTER_CHOOSER(COUNT)

Definition at line 4019 of file Generator.h.

◆ _HALIDE_REGISTER_GENERATOR_PASTE

#define _HALIDE_REGISTER_GENERATOR_PASTE (   A,
 
)    A B

Definition at line 4022 of file Generator.h.

◆ HALIDE_REGISTER_GENERATOR

#define HALIDE_REGISTER_GENERATOR (   ...)    _HALIDE_REGISTER_GENERATOR_PASTE(_HALIDE_REGISTER_CHOOSER(_HALIDE_REGISTER_ARGCOUNT(__VA_ARGS__)), (__VA_ARGS__))
Examples
tutorial/lesson_15_generators.cpp.

Definition at line 4025 of file Generator.h.

◆ HALIDE_REGISTER_GENERATOR_ALIAS

#define HALIDE_REGISTER_GENERATOR_ALIAS (   GEN_REGISTRY_NAME,
  ORIGINAL_REGISTRY_NAME,
  ... 
)
Value:
struct halide_global_ns; \
namespace ORIGINAL_REGISTRY_NAME##_ns { \
std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
} \
namespace GEN_REGISTRY_NAME##_ns { \
std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context) { \
auto g = ORIGINAL_REGISTRY_NAME##_ns::factory(context); \
const Halide::GeneratorParamsMap m = __VA_ARGS__; \
g->set_generatorparam_values(m); \
return g; \
} \
} \
static auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
} \
static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
"HALIDE_REGISTER_GENERATOR_ALIAS must be used at global scope");

Definition at line 4042 of file Generator.h.

◆ HALIDE_GENERATOR_PYSTUB

#define HALIDE_GENERATOR_PYSTUB (   GEN_REGISTRY_NAME,
  MODULE_NAME 
)
Value:
static_assert(PY_MAJOR_VERSION >= 3, "Python bindings for Halide require Python 3+"); \
extern "C" PyObject *_halide_pystub_impl(const char *module_name, const Halide::Internal::GeneratorFactory &factory); \
namespace halide_register_generator::GEN_REGISTRY_NAME##_ns { \
extern std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
} \
extern "C" HALIDE_EXPORT_SYMBOL PyObject *PyInit_##MODULE_NAME() { \
const auto factory = halide_register_generator::GEN_REGISTRY_NAME##_ns::factory; \
return _halide_pystub_impl(#MODULE_NAME, factory); \
}

Definition at line 4064 of file Generator.h.

Halide::sum
Expr sum(Expr, const std::string &s="sum")
An inline reduction.
Halide::Float
Type Float(int bits, int lanes=1)
Construct a floating-point type.
Definition: Type.h:536
Halide::GeneratorParamsMap
std::map< std::string, std::string > GeneratorParamsMap
Definition: AbstractGenerator.h:22
Halide::Internal::GeneratorFactory
std::function< AbstractGeneratorPtr(const GeneratorContext &context)> GeneratorFactory
Definition: Generator.h:3105
Halide::UInt
Type UInt(int bits, int lanes=1)
Constructing an unsigned integer type.
Definition: Type.h:531
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
Halide::OutputFileType::schedule
@ schedule
halide_register_generator
Definition: Generator.h:3976
HALIDE_EXPORT_SYMBOL
#define HALIDE_EXPORT_SYMBOL
Definition: HalideRuntime.h:74
Halide::Internal::RegisterGenerator
Definition: Generator.h:3872
HALIDE_REGISTER_GENERATOR
#define HALIDE_REGISTER_GENERATOR(...)
Definition: Generator.h:4025
Halide::Int
Type Int(int bits, int lanes=1)
Constructing a signed integer type.
Definition: Type.h:526