Halide
Pipeline.h
Go to the documentation of this file.
1 #ifndef HALIDE_PIPELINE_H
2 #define HALIDE_PIPELINE_H
3 
4 /** \file
5  *
6  * Defines the front-end class representing an entire Halide imaging
7  * pipeline.
8  */
9 
10 #include <map>
11 #include <vector>
12 
13 #include "ExternalCode.h"
14 #include "IROperator.h"
15 #include "IntrusivePtr.h"
16 #include "JITModule.h"
17 #include "Module.h"
18 #include "ParamMap.h"
19 #include "Realization.h"
20 #include "Target.h"
21 #include "Tuple.h"
22 
23 namespace Halide {
24 
25 struct Argument;
26 class Func;
27 struct PipelineContents;
28 
29 /** A struct representing the machine parameters to generate the auto-scheduled
30  * code for. */
31 struct MachineParams {
32  /** Maximum level of parallelism avalaible. */
34  /** Size of the last-level cache (in bytes). */
36  /** Indicates how much more expensive is the cost of a load compared to
37  * the cost of an arithmetic operation at last level cache. */
38  float balance;
39 
40  explicit MachineParams(int parallelism, uint64_t llc, float balance)
42  }
43 
44  /** Default machine parameters for generic CPU architecture. */
45  static MachineParams generic();
46 
47  /** Convert the MachineParams into canonical string form. */
48  std::string to_string() const;
49 
50  /** Reconstruct a MachineParams from canonical string form. */
51  explicit MachineParams(const std::string &s);
52 };
53 
54 namespace Internal {
55 class IRMutator;
56 } // namespace Internal
57 
58 /**
59  * Used to determine if the output printed to file should be as a normal string
60  * or as an HTML file which can be opened in a browerser and manipulated via JS and CSS.*/
64 };
65 
66 namespace {
67 // Helper for deleting custom lowering passes. In the header so that
68 // it goes in user code on windows, where you can have multiple heaps.
69 template<typename T>
70 void delete_lowering_pass(T *pass) {
71  delete pass;
72 }
73 } // namespace
74 
75 /** A custom lowering pass. See Pipeline::add_custom_lowering_pass. */
78  std::function<void()> deleter;
79 };
80 
81 struct JITExtern;
82 
84  std::string scheduler_name; // name of the autoscheduler used
85  Target target; // Target specified to the autoscheduler
86  std::string machine_params_string; // MachineParams specified to the autoscheduler (in string form)
87  std::string schedule_source; // The C++ source code of the generated schedule
88  std::vector<uint8_t> featurization; // The featurization of the pipeline (if any)
89 };
90 
91 class Pipeline;
92 
93 using AutoSchedulerFn = std::function<void(const Pipeline &, const Target &, const MachineParams &, AutoSchedulerResults *outputs)>;
94 
95 /** A class representing a Halide pipeline. Constructed from the Func
96  * or Funcs that it outputs. */
97 class Pipeline {
98 public:
99  struct RealizationArg {
100  // Only one of the following may be non-null
101  Realization *r{nullptr};
102  halide_buffer_t *buf{nullptr};
103  std::unique_ptr<std::vector<Buffer<>>> buffer_list;
104 
106  : r(&r) {
107  }
109  : r(&r) {
110  }
112  : buf(buf) {
113  }
114  template<typename T, int D>
116  : buf(dst.raw_buffer()) {
117  }
118  template<typename T>
120  : buf(dst.raw_buffer()) {
121  }
122  template<typename T, typename... Args,
123  typename = typename std::enable_if<Internal::all_are_convertible<Buffer<>, Args...>::value>::type>
124  RealizationArg(Buffer<T> &a, Args &&... args) {
125  buffer_list.reset(new std::vector<Buffer<>>({a, args...}));
126  }
127  RealizationArg(RealizationArg &&from) = default;
128 
129  size_t size() const {
130  if (r != nullptr) {
131  return r->size();
132  } else if (buffer_list) {
133  return buffer_list->size();
134  }
135  return 1;
136  }
137  };
138 
139 private:
141 
142  struct JITCallArgs; // Opaque structure to optimize away dynamic allocation in this path.
143 
144  // For the three method below, precisely one of the first two args should be non-null
145  void prepare_jit_call_arguments(RealizationArg &output, const Target &target, const ParamMap &param_map,
146  void *user_context, bool is_bounds_inference, JITCallArgs &args_result);
147 
148  static std::vector<Internal::JITModule> make_externs_jit_module(const Target &target,
149  std::map<std::string, JITExtern> &externs_in_out);
150 
151  static std::map<std::string, AutoSchedulerFn> &get_autoscheduler_map();
152 
153  static std::string &get_default_autoscheduler_name();
154 
155  static AutoSchedulerFn find_autoscheduler(const std::string &autoscheduler_name);
156 
157  int call_jit_code(const Target &target, const JITCallArgs &args);
158 
159  // Get the value of contents->jit_target, but reality-check that the contents
160  // sensibly match the value. Return Target() if not jitted.
161  Target get_compiled_jit_target() const;
162 
163 public:
164  /** Make an undefined Pipeline object. */
165  Pipeline();
166 
167  /** Make a pipeline that computes the given Func. Schedules the
168  * Func compute_root(). */
169  Pipeline(const Func &output);
170 
171  /** Make a pipeline that computes the givens Funcs as
172  * outputs. Schedules the Funcs compute_root(). */
173  Pipeline(const std::vector<Func> &outputs);
174 
175  std::vector<Argument> infer_arguments(const Internal::Stmt &body);
176 
177  /** Get the Funcs this pipeline outputs. */
178  std::vector<Func> outputs() const;
179 
180  /** Generate a schedule for the pipeline using the currently-default autoscheduler. */
182  const MachineParams &arch_params = MachineParams::generic());
183 
184  /** Generate a schedule for the pipeline using the specified autoscheduler. */
185  AutoSchedulerResults auto_schedule(const std::string &autoscheduler_name,
186  const Target &target,
187  const MachineParams &arch_params = MachineParams::generic());
188 
189  /** Add a new the autoscheduler method with the given name. Does not affect the current default autoscheduler.
190  * It is an error to call this with the same name multiple times. */
191  static void add_autoscheduler(const std::string &autoscheduler_name, const AutoSchedulerFn &autoscheduler);
192 
193  /** Globally set the default autoscheduler method to use whenever
194  * autoscheduling any Pipeline when no name is specified. If the autoscheduler_name isn't in the
195  * current table of known autoschedulers, assert-fail.
196  *
197  * At this time, well-known autoschedulers include:
198  * "Mullapudi2016" -- heuristics-based; the first working autoscheduler; currently built in to libHalide
199  * see http://graphics.cs.cmu.edu/projects/halidesched/
200  * "Adams2019" -- aka "the ML autoscheduler"; currently located in apps/autoscheduler
201  * see https://halide-lang.org/papers/autoscheduler2019.html
202  * "Li2018" -- aka "the gradient autoscheduler"; currently located in apps/gradient_autoscheduler.
203  * see https://people.csail.mit.edu/tzumao/gradient_halide
204  */
205  static void set_default_autoscheduler_name(const std::string &autoscheduler_name);
206 
207  /** Return handle to the index-th Func within the pipeline based on the
208  * topological order. */
209  Func get_func(size_t index);
210 
211  /** Compile and generate multiple target files with single call.
212  * Deduces target files based on filenames specified in
213  * output_files map.
214  */
215  void compile_to(const std::map<Output, std::string> &output_files,
216  const std::vector<Argument> &args,
217  const std::string &fn_name,
218  const Target &target);
219 
220  /** Statically compile a pipeline to llvm bitcode, with the given
221  * filename (which should probably end in .bc), type signature,
222  * and C function name. If you're compiling a pipeline with a
223  * single output Func, see also Func::compile_to_bitcode. */
224  void compile_to_bitcode(const std::string &filename,
225  const std::vector<Argument> &args,
226  const std::string &fn_name,
227  const Target &target = get_target_from_environment());
228 
229  /** Statically compile a pipeline to llvm assembly, with the given
230  * filename (which should probably end in .ll), type signature,
231  * and C function name. If you're compiling a pipeline with a
232  * single output Func, see also Func::compile_to_llvm_assembly. */
233  void compile_to_llvm_assembly(const std::string &filename,
234  const std::vector<Argument> &args,
235  const std::string &fn_name,
236  const Target &target = get_target_from_environment());
237 
238  /** Statically compile a pipeline with multiple output functions to an
239  * object file, with the given filename (which should probably end in
240  * .o or .obj), type signature, and C function name (which defaults to
241  * the same name as this halide function. You probably don't want to
242  * use this directly; call compile_to_static_library or compile_to_file instead. */
243  void compile_to_object(const std::string &filename,
244  const std::vector<Argument> &,
245  const std::string &fn_name,
246  const Target &target = get_target_from_environment());
247 
248  /** Emit a header file with the given filename for a pipeline. The
249  * header will define a function with the type signature given by
250  * the second argument, and a name given by the third. You don't
251  * actually have to have defined any of these functions yet to
252  * call this. You probably don't want to use this directly; call
253  * compile_to_static_library or compile_to_file instead. */
254  void compile_to_header(const std::string &filename,
255  const std::vector<Argument> &,
256  const std::string &fn_name,
257  const Target &target = get_target_from_environment());
258 
259  /** Statically compile a pipeline to text assembly equivalent to
260  * the object file generated by compile_to_object. This is useful
261  * for checking what Halide is producing without having to
262  * disassemble anything, or if you need to feed the assembly into
263  * some custom toolchain to produce an object file. */
264  void compile_to_assembly(const std::string &filename,
265  const std::vector<Argument> &args,
266  const std::string &fn_name,
267  const Target &target = get_target_from_environment());
268 
269  /** Statically compile a pipeline to C source code. This is useful
270  * for providing fallback code paths that will compile on many
271  * platforms. Vectorization will fail, and parallelization will
272  * produce serial code. */
273  void compile_to_c(const std::string &filename,
274  const std::vector<Argument> &,
275  const std::string &fn_name,
276  const Target &target = get_target_from_environment());
277 
278  /** Write out an internal representation of lowered code. Useful
279  * for analyzing and debugging scheduling. Can emit html or plain
280  * text. */
281  void compile_to_lowered_stmt(const std::string &filename,
282  const std::vector<Argument> &args,
283  StmtOutputFormat fmt = Text,
284  const Target &target = get_target_from_environment());
285 
286  /** Write out the loop nests specified by the schedule for this
287  * Pipeline's Funcs. Helpful for understanding what a schedule is
288  * doing. */
289  void print_loop_nest();
290 
291  /** Compile to object file and header pair, with the given
292  * arguments. */
293  void compile_to_file(const std::string &filename_prefix,
294  const std::vector<Argument> &args,
295  const std::string &fn_name,
296  const Target &target = get_target_from_environment());
297 
298  /** Compile to static-library file and header pair, with the given
299  * arguments. */
300  void compile_to_static_library(const std::string &filename_prefix,
301  const std::vector<Argument> &args,
302  const std::string &fn_name,
303  const Target &target = get_target_from_environment());
304 
305  /** Compile to static-library file and header pair once for each target;
306  * each resulting function will be considered (in order) via halide_can_use_target_features()
307  * at runtime, with the first appropriate match being selected for subsequent use.
308  * This is typically useful for specializations that may vary unpredictably by machine
309  * (e.g., SSE4.1/AVX/AVX2 on x86 desktop machines).
310  * All targets must have identical arch-os-bits.
311  */
312  void compile_to_multitarget_static_library(const std::string &filename_prefix,
313  const std::vector<Argument> &args,
314  const std::vector<Target> &targets);
315 
316  /** Like compile_to_multitarget_static_library(), except that the object files
317  * are all output as object files (rather than bundled into a static library).
318  *
319  * `suffixes` is an optional list of strings to use for as the suffix for each object
320  * file. If nonempty, it must be the same length as `targets`. (If empty, Target::to_string()
321  * will be used for each suffix.)
322  *
323  * Note that if `targets.size()` > 1, the wrapper code (to select the subtarget)
324  * will be generated with the filename `${filename_prefix}_wrapper.o`
325  *
326  * Note that if `targets.size()` > 1 and `no_runtime` is not specified, the runtime
327  * will be generated with the filename `${filename_prefix}_runtime.o`
328  */
329  void compile_to_multitarget_object_files(const std::string &filename_prefix,
330  const std::vector<Argument> &args,
331  const std::vector<Target> &targets,
332  const std::vector<std::string> &suffixes);
333 
334  /** Create an internal representation of lowered code as a self
335  * contained Module suitable for further compilation. */
336  Module compile_to_module(const std::vector<Argument> &args,
337  const std::string &fn_name,
338  const Target &target = get_target_from_environment(),
339  const LinkageType linkage_type = LinkageType::ExternalPlusMetadata);
340 
341  /** Eagerly jit compile the function to machine code. This
342  * normally happens on the first call to realize. If you're
343  * running your halide pipeline inside time-sensitive code and
344  * wish to avoid including the time taken to compile a pipeline,
345  * then you can call this ahead of time. Default is to use the Target
346  * returned from Halide::get_jit_target_from_environment()
347  */
348  void compile_jit(const Target &target = get_jit_target_from_environment());
349 
350  /** Set the error handler function that be called in the case of
351  * runtime errors during halide pipelines. If you are compiling
352  * statically, you can also just define your own function with
353  * signature
354  \code
355  extern "C" void halide_error(void *user_context, const char *);
356  \endcode
357  * This will clobber Halide's version.
358  */
359  void set_error_handler(void (*handler)(void *, const char *));
360 
361  /** Set a custom malloc and free for halide to use. Malloc should
362  * return 32-byte aligned chunks of memory, and it should be safe
363  * for Halide to read slightly out of bounds (up to 8 bytes before
364  * the start or beyond the end). If compiling statically, routines
365  * with appropriate signatures can be provided directly
366  \code
367  extern "C" void *halide_malloc(void *, size_t)
368  extern "C" void halide_free(void *, void *)
369  \endcode
370  * These will clobber Halide's versions. See HalideRuntime.h
371  * for declarations.
372  */
373  void set_custom_allocator(void *(*malloc)(void *, size_t),
374  void (*free)(void *, void *));
375 
376  /** Set a custom task handler to be called by the parallel for
377  * loop. It is useful to set this if you want to do some
378  * additional bookkeeping at the granularity of parallel
379  * tasks. The default implementation does this:
380  \code
381  extern "C" int halide_do_task(void *user_context,
382  int (*f)(void *, int, uint8_t *),
383  int idx, uint8_t *state) {
384  return f(user_context, idx, state);
385  }
386  \endcode
387  * If you are statically compiling, you can also just define your
388  * own version of the above function, and it will clobber Halide's
389  * version.
390  *
391  * If you're trying to use a custom parallel runtime, you probably
392  * don't want to call this. See instead \ref Func::set_custom_do_par_for .
393  */
394  void set_custom_do_task(
395  int (*custom_do_task)(void *, int (*)(void *, int, uint8_t *),
396  int, uint8_t *));
397 
398  /** Set a custom parallel for loop launcher. Useful if your app
399  * already manages a thread pool. The default implementation is
400  * equivalent to this:
401  \code
402  extern "C" int halide_do_par_for(void *user_context,
403  int (*f)(void *, int, uint8_t *),
404  int min, int extent, uint8_t *state) {
405  int exit_status = 0;
406  parallel for (int idx = min; idx < min+extent; idx++) {
407  int job_status = halide_do_task(user_context, f, idx, state);
408  if (job_status) exit_status = job_status;
409  }
410  return exit_status;
411  }
412  \endcode
413  *
414  * However, notwithstanding the above example code, if one task
415  * fails, we may skip over other tasks, and if two tasks return
416  * different error codes, we may select one arbitrarily to return.
417  *
418  * If you are statically compiling, you can also just define your
419  * own version of the above function, and it will clobber Halide's
420  * version.
421  */
423  int (*custom_do_par_for)(void *, int (*)(void *, int, uint8_t *), int,
424  int, uint8_t *));
425 
426  /** Set custom routines to call when tracing is enabled. Call this
427  * on the output Func of your pipeline. This then sets custom
428  * routines for the entire pipeline, not just calls to this
429  * Func.
430  *
431  * If you are statically compiling, you can also just define your
432  * own versions of the tracing functions (see HalideRuntime.h),
433  * and they will clobber Halide's versions. */
434  void set_custom_trace(int (*trace_fn)(void *, const halide_trace_event_t *));
435 
436  /** Set the function called to print messages from the runtime.
437  * If you are compiling statically, you can also just define your
438  * own function with signature
439  \code
440  extern "C" void halide_print(void *user_context, const char *);
441  \endcode
442  * This will clobber Halide's version.
443  */
444  void set_custom_print(void (*handler)(void *, const char *));
445 
446  /** Install a set of external C functions or Funcs to satisfy
447  * dependencies introduced by HalideExtern and define_extern
448  * mechanisms. These will be used by calls to realize,
449  * infer_bounds, and compile_jit. */
450  void set_jit_externs(const std::map<std::string, JITExtern> &externs);
451 
452  /** Return the map of previously installed externs. Is an empty
453  * map unless set otherwise. */
454  const std::map<std::string, JITExtern> &get_jit_externs();
455 
456  /** Get a struct containing the currently set custom functions
457  * used by JIT. */
459 
460  /** Add a custom pass to be used during lowering. It is run after
461  * all other lowering passes. Can be used to verify properties of
462  * the lowered Stmt, instrument it with extra code, or otherwise
463  * modify it. The Func takes ownership of the pass, and will call
464  * delete on it when the Func goes out of scope. So don't pass a
465  * stack object, or share pass instances between multiple
466  * Funcs. */
467  template<typename T>
468  void add_custom_lowering_pass(T *pass) {
469  // Template instantiate a custom deleter for this type, then
470  // wrap in a lambda. The custom deleter lives in user code, so
471  // that deletion is on the same heap as construction (I hate Windows).
472  add_custom_lowering_pass(pass, [pass]() { delete_lowering_pass<T>(pass); });
473  }
474 
475  /** Add a custom pass to be used during lowering, with the
476  * function that will be called to delete it also passed in. Set
477  * it to nullptr if you wish to retain ownership of the object. */
478  void add_custom_lowering_pass(Internal::IRMutator *pass, std::function<void()> deleter);
479 
480  /** Remove all previously-set custom lowering passes */
482 
483  /** Get the custom lowering passes. */
484  const std::vector<CustomLoweringPass> &custom_lowering_passes();
485 
486  /** See Func::realize */
487  // @{
488  Realization realize(std::vector<int32_t> sizes, const Target &target = Target(),
489  const ParamMap &param_map = ParamMap::empty_map());
490  Realization realize(int x_size, int y_size, int z_size, int w_size, const Target &target = Target(),
491  const ParamMap &param_map = ParamMap::empty_map());
492  Realization realize(int x_size, int y_size, int z_size, const Target &target = Target(),
493  const ParamMap &param_map = ParamMap::empty_map());
494  Realization realize(int x_size, int y_size, const Target &target = Target(),
495  const ParamMap &param_map = ParamMap::empty_map());
496  Realization realize(int x_size, const Target &target = Target(),
497  const ParamMap &param_map = ParamMap::empty_map());
498  Realization realize(const Target &target = Target(),
499  const ParamMap &param_map = ParamMap::empty_map());
500  // @}
501 
502  /** Evaluate this Pipeline into an existing allocated buffer or
503  * buffers. If the buffer is also one of the arguments to the
504  * function, strange things may happen, as the pipeline isn't
505  * necessarily safe to run in-place. The realization should
506  * contain one Buffer per tuple component per output Func. For
507  * each individual output Func, all Buffers must have the same
508  * shape, but the shape can vary across the different output
509  * Funcs. This form of realize does *not* automatically copy data
510  * back from the GPU. */
511  void realize(RealizationArg output, const Target &target = Target(),
512  const ParamMap &param_map = ParamMap::empty_map());
513 
514  /** For a given size of output, or a given set of output buffers,
515  * determine the bounds required of all unbound ImageParams
516  * referenced. Communicates the result by allocating new buffers
517  * of the appropriate size and binding them to the unbound
518  * ImageParams. */
519  // @{
520  void infer_input_bounds(const std::vector<int32_t> &sizes,
521  const Target &target = get_jit_target_from_environment(),
522  const ParamMap &param_map = ParamMap::empty_map());
523  HALIDE_ATTRIBUTE_DEPRECATED("Call infer_input_bounds() with an explicit vector<int> instead")
524  void infer_input_bounds(int x_size = 0, int y_size = 0, int z_size = 0, int w_size = 0,
525  const Target &target = get_jit_target_from_environment(),
526  const ParamMap &param_map = ParamMap::empty_map());
527  // TODO: this is a temporary wrapper used to disambiguate the cases where
528  // a single-entry braced list would match the deprecated overload
529  // (rather than the vector overload); when the deprecated method is removed,
530  // this should be removed, too
531  void infer_input_bounds(const std::initializer_list<int> &sizes,
532  const Target &target = get_jit_target_from_environment(),
533  const ParamMap &param_map = ParamMap::empty_map()) {
534  infer_input_bounds(std::vector<int>{sizes}, target, param_map);
535  }
536  void infer_input_bounds(RealizationArg output,
537  const Target &target = get_jit_target_from_environment(),
538  const ParamMap &param_map = ParamMap::empty_map());
539  // @}
540 
541  /** Infer the arguments to the Pipeline, sorted into a canonical order:
542  * all buffers (sorted alphabetically by name), followed by all non-buffers
543  * (sorted alphabetically by name).
544  This lets you write things like:
545  \code
546  pipeline.compile_to_assembly("/dev/stdout", pipeline.infer_arguments());
547  \endcode
548  */
549  std::vector<Argument> infer_arguments();
550 
551  /** Check if this pipeline object is defined. That is, does it
552  * have any outputs? */
553  bool defined() const;
554 
555  /** Invalidate any internal cached state, e.g. because Funcs have
556  * been rescheduled. */
557  void invalidate_cache();
558 
559  /** Add a top-level precondition to the generated pipeline,
560  * expressed as a boolean Expr. The Expr may depend on parameters
561  * only, and may not call any Func or use a Var. If the condition
562  * is not true at runtime, the pipeline will call halide_error
563  * with the remaining arguments, and return
564  * halide_error_code_requirement_failed. Requirements are checked
565  * in the order added. */
566  void add_requirement(const Expr &condition, std::vector<Expr> &error);
567 
568  /** Generate begin_pipeline and end_pipeline tracing calls for this pipeline. */
569  void trace_pipeline();
570 
571  template<typename... Args>
572  inline HALIDE_NO_USER_CODE_INLINE void add_requirement(const Expr &condition, Args &&... args) {
573  std::vector<Expr> collected_args;
574  Internal::collect_print_args(collected_args, std::forward<Args>(args)...);
575  add_requirement(condition, collected_args);
576  }
577 
578 private:
579  std::string generate_function_name() const;
580 };
581 
583 private:
584  Type ret_type_; // Only meaningful if is_void_return is false; must be default value otherwise
585  bool is_void_return_{false};
586  std::vector<Type> arg_types_;
587 
588 public:
589  ExternSignature() = default;
590 
591  ExternSignature(const Type &ret_type, bool is_void_return, const std::vector<Type> &arg_types)
592  : ret_type_(ret_type),
593  is_void_return_(is_void_return),
594  arg_types_(arg_types) {
596  }
597 
598  template<typename RT, typename... Args>
599  explicit ExternSignature(RT (*f)(Args... args))
600  : ret_type_(type_of<RT>()),
601  is_void_return_(std::is_void<RT>::value),
602  arg_types_({type_of<Args>()...}) {
603  }
604 
605  const Type &ret_type() const {
607  return ret_type_;
608  }
609 
610  bool is_void_return() const {
611  return is_void_return_;
612  }
613 
614  const std::vector<Type> &arg_types() const {
615  return arg_types_;
616  }
617 
618  friend std::ostream &operator<<(std::ostream &stream, const ExternSignature &sig) {
619  if (sig.is_void_return_) {
620  stream << "void";
621  } else {
622  stream << sig.ret_type_;
623  }
624  stream << " (*)(";
625  bool comma = false;
626  for (const auto &t : sig.arg_types_) {
627  if (comma) stream << ", ";
628  stream << t;
629  comma = true;
630  }
631  stream << ")";
632  return stream;
633  }
634 };
635 
637 private:
638  void *address_{nullptr};
639  ExternSignature signature_;
640 
641 public:
642  ExternCFunction() = default;
643 
645  : address_(address), signature_(signature) {
646  }
647 
648  template<typename RT, typename... Args>
649  ExternCFunction(RT (*f)(Args... args))
650  : ExternCFunction((void *)f, ExternSignature(f)) {
651  }
652 
653  void *address() const {
654  return address_;
655  }
656  const ExternSignature &signature() const {
657  return signature_;
658  }
659 };
660 
661 struct JITExtern {
662 private:
663  // Note that exactly one of pipeline_ and extern_c_function_
664  // can be set in a given JITExtern instance.
665  Pipeline pipeline_;
666  ExternCFunction extern_c_function_;
667 
668 public:
669  explicit JITExtern(Pipeline pipeline);
670  explicit JITExtern(const Func &func);
672 
673  template<typename RT, typename... Args>
674  explicit JITExtern(RT (*f)(Args... args))
675  : JITExtern(ExternCFunction(f)) {
676  }
677 
678  const Pipeline &pipeline() const {
679  return pipeline_;
680  }
682  return extern_c_function_;
683  }
684 };
685 
686 } // namespace Halide
687 
688 #endif
Halide::JITExtern::JITExtern
JITExtern(Pipeline pipeline)
Halide::MachineParams
A struct representing the machine parameters to generate the auto-scheduled code for.
Definition: Pipeline.h:31
Halide::Pipeline::auto_schedule
AutoSchedulerResults auto_schedule(const Target &target, const MachineParams &arch_params=MachineParams::generic())
Generate a schedule for the pipeline using the currently-default autoscheduler.
halide_trace_event_t
Definition: HalideRuntime.h:501
Tuple.h
Halide::Pipeline::RealizationArg::RealizationArg
RealizationArg(halide_buffer_t *buf)
Definition: Pipeline.h:111
internal_assert
#define internal_assert(c)
Definition: Errors.h:19
Halide::Pipeline::set_custom_do_par_for
void set_custom_do_par_for(int(*custom_do_par_for)(void *, int(*)(void *, int, uint8_t *), int, int, uint8_t *))
Set a custom parallel for loop launcher.
uint8_t
unsigned __INT8_TYPE__ uint8_t
Definition: runtime_internal.h:25
Halide::Pipeline::compile_to_header
void compile_to_header(const std::string &filename, const std::vector< Argument > &, const std::string &fn_name, const Target &target=get_target_from_environment())
Emit a header file with the given filename for a pipeline.
Halide::Pipeline::RealizationArg::RealizationArg
RealizationArg(Runtime::Buffer< T, D > &dst)
Definition: Pipeline.h:115
Halide::Pipeline::add_autoscheduler
static void add_autoscheduler(const std::string &autoscheduler_name, const AutoSchedulerFn &autoscheduler)
Add a new the autoscheduler method with the given name.
Halide::Pipeline::compile_to_module
Module compile_to_module(const std::vector< Argument > &args, const std::string &fn_name, const Target &target=get_target_from_environment(), const LinkageType linkage_type=LinkageType::ExternalPlusMetadata)
Create an internal representation of lowered code as a self contained Module suitable for further com...
Halide::MachineParams::MachineParams
MachineParams(int parallelism, uint64_t llc, float balance)
Definition: Pipeline.h:40
Halide::HTML
@ HTML
Definition: Pipeline.h:63
Halide::Pipeline::RealizationArg
Definition: Pipeline.h:99
Halide::MachineParams::to_string
std::string to_string() const
Convert the MachineParams into canonical string form.
IROperator.h
Halide::StmtOutputFormat
StmtOutputFormat
Used to determine if the output printed to file should be as a normal string or as an HTML file which...
Definition: Pipeline.h:61
Halide::MachineParams::parallelism
int parallelism
Maximum level of parallelism avalaible.
Definition: Pipeline.h:33
Halide::Pipeline::compile_to_assembly
void compile_to_assembly(const std::string &filename, const std::vector< Argument > &args, const std::string &fn_name, const Target &target=get_target_from_environment())
Statically compile a pipeline to text assembly equivalent to the object file generated by compile_to_...
Halide::ExternCFunction::ExternCFunction
ExternCFunction()=default
Target.h
Halide::Pipeline::RealizationArg::RealizationArg
RealizationArg(Realization &r)
Definition: Pipeline.h:105
Halide::AutoSchedulerResults::scheduler_name
std::string scheduler_name
Definition: Pipeline.h:84
Halide::Pipeline::Pipeline
Pipeline()
Make an undefined Pipeline object.
Halide::Pipeline::clear_custom_lowering_passes
void clear_custom_lowering_passes()
Remove all previously-set custom lowering passes.
Halide::ParamMap
Definition: ParamMap.h:17
Halide::AutoSchedulerFn
std::function< void(const Pipeline &, const Target &, const MachineParams &, AutoSchedulerResults *outputs)> AutoSchedulerFn
Definition: Pipeline.h:93
Halide::Pipeline::set_custom_print
void set_custom_print(void(*handler)(void *, const char *))
Set the function called to print messages from the runtime.
Halide::Pipeline::invalidate_cache
void invalidate_cache()
Invalidate any internal cached state, e.g.
Halide::get_target_from_environment
Target get_target_from_environment()
Return the target that Halide will use.
Halide::Pipeline::compile_to_file
void compile_to_file(const std::string &filename_prefix, const std::vector< Argument > &args, const std::string &fn_name, const Target &target=get_target_from_environment())
Compile to object file and header pair, with the given arguments.
Halide::Text
@ Text
Definition: Pipeline.h:62
Halide::Pipeline::add_requirement
HALIDE_NO_USER_CODE_INLINE void add_requirement(const Expr &condition, Args &&... args)
Definition: Pipeline.h:572
Halide::Pipeline::RealizationArg::buf
halide_buffer_t * buf
Definition: Pipeline.h:102
Halide::Internal::IntrusivePtr< PipelineContents >
Halide::Pipeline::RealizationArg::buffer_list
std::unique_ptr< std::vector< Buffer<> > > buffer_list
Definition: Pipeline.h:103
Halide::CustomLoweringPass::deleter
std::function< void()> deleter
Definition: Pipeline.h:78
Halide::Internal::Stmt
A reference-counted handle to a statement node.
Definition: Expr.h:409
uint64_t
unsigned __INT64_TYPE__ uint64_t
Definition: runtime_internal.h:19
Halide::Pipeline::RealizationArg::RealizationArg
RealizationArg(Buffer< T > &a, Args &&... args)
Definition: Pipeline.h:124
Halide::Pipeline::infer_arguments
std::vector< Argument > infer_arguments()
Infer the arguments to the Pipeline, sorted into a canonical order: all buffers (sorted alphabeticall...
Halide::ExternSignature::ExternSignature
ExternSignature(RT(*f)(Args... args))
Definition: Pipeline.h:599
malloc
void * malloc(size_t)
ExternalCode.h
Halide::Module
A halide module.
Definition: Module.h:136
Halide::Type
Types in the halide type system.
Definition: Type.h:269
Halide::ExternCFunction
Definition: Pipeline.h:636
Halide::Pipeline
A class representing a Halide pipeline.
Definition: Pipeline.h:97
Halide::Pipeline::RealizationArg::RealizationArg
HALIDE_NO_USER_CODE_INLINE RealizationArg(Buffer< T > &dst)
Definition: Pipeline.h:119
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AddAtomicMutex.h:21
Halide::Pipeline::compile_to_object
void compile_to_object(const std::string &filename, const std::vector< Argument > &, const std::string &fn_name, const Target &target=get_target_from_environment())
Statically compile a pipeline with multiple output functions to an object file, with the given filena...
Halide::CustomLoweringPass
A custom lowering pass.
Definition: Pipeline.h:76
Halide::AutoSchedulerResults::machine_params_string
std::string machine_params_string
Definition: Pipeline.h:86
Halide::Pipeline::compile_to_lowered_stmt
void compile_to_lowered_stmt(const std::string &filename, const std::vector< Argument > &args, StmtOutputFormat fmt=Text, const Target &target=get_target_from_environment())
Write out an internal representation of lowered code.
Halide::Pipeline::RealizationArg::RealizationArg
RealizationArg(Realization &&r)
Definition: Pipeline.h:108
Halide::LinkageType
LinkageType
Type of linkage a function in a lowered Halide module can have.
Definition: Module.h:49
Halide::Pipeline::realize
Realization realize(std::vector< int32_t > sizes, const Target &target=Target(), const ParamMap &param_map=ParamMap::empty_map())
See Func::realize.
JITModule.h
Halide::Buffer
A Halide::Buffer is a named shared reference to a Halide::Runtime::Buffer.
Definition: Argument.h:16
Halide::Pipeline::set_jit_externs
void set_jit_externs(const std::map< std::string, JITExtern > &externs)
Install a set of external C functions or Funcs to satisfy dependencies introduced by HalideExtern and...
Halide::Pipeline::infer_input_bounds
void infer_input_bounds(const std::vector< int32_t > &sizes, const Target &target=get_jit_target_from_environment(), const ParamMap &param_map=ParamMap::empty_map())
For a given size of output, or a given set of output buffers, determine the bounds required of all un...
Halide::Internal::JITHandlers
Definition: JITModule.h:139
Halide::Internal::collect_print_args
HALIDE_NO_USER_CODE_INLINE void collect_print_args(std::vector< Expr > &args)
Definition: IROperator.h:319
HALIDE_ATTRIBUTE_DEPRECATED
#define HALIDE_ATTRIBUTE_DEPRECATED(x)
Definition: HalideRuntime.h:1544
Halide::CustomLoweringPass::pass
Internal::IRMutator * pass
Definition: Pipeline.h:77
Halide::ExternSignature::arg_types
const std::vector< Type > & arg_types() const
Definition: Pipeline.h:614
Halide::Runtime::Buffer
A templated Buffer class that wraps halide_buffer_t and adds functionality.
Definition: HalideBuffer.h:43
ParamMap.h
Halide::MachineParams::last_level_cache_size
uint64_t last_level_cache_size
Size of the last-level cache (in bytes).
Definition: Pipeline.h:35
Halide::Pipeline::RealizationArg::r
Realization * r
Definition: Pipeline.h:101
Halide::ExternCFunction::ExternCFunction
ExternCFunction(void *address, const ExternSignature &signature)
Definition: Pipeline.h:644
Halide::Pipeline::compile_to_multitarget_static_library
void compile_to_multitarget_static_library(const std::string &filename_prefix, const std::vector< Argument > &args, const std::vector< Target > &targets)
Compile to static-library file and header pair once for each target; each resulting function will be ...
Halide::JITExtern::JITExtern
JITExtern(RT(*f)(Args... args))
Definition: Pipeline.h:674
Halide::ExternCFunction::address
void * address() const
Definition: Pipeline.h:653
Halide::Pipeline::add_requirement
void add_requirement(const Expr &condition, std::vector< Expr > &error)
Add a top-level precondition to the generated pipeline, expressed as a boolean Expr.
Halide::Pipeline::compile_to_static_library
void compile_to_static_library(const std::string &filename_prefix, const std::vector< Argument > &args, const std::string &fn_name, const Target &target=get_target_from_environment())
Compile to static-library file and header pair, with the given arguments.
Halide::AutoSchedulerResults::schedule_source
std::string schedule_source
Definition: Pipeline.h:87
Halide::Pipeline::compile_to
void compile_to(const std::map< Output, std::string > &output_files, const std::vector< Argument > &args, const std::string &fn_name, const Target &target)
Compile and generate multiple target files with single call.
Halide::Pipeline::compile_to_bitcode
void compile_to_bitcode(const std::string &filename, const std::vector< Argument > &args, const std::string &fn_name, const Target &target=get_target_from_environment())
Statically compile a pipeline to llvm bitcode, with the given filename (which should probably end in ...
Halide::Pipeline::set_default_autoscheduler_name
static void set_default_autoscheduler_name(const std::string &autoscheduler_name)
Globally set the default autoscheduler method to use whenever autoscheduling any Pipeline when no nam...
Halide::Pipeline::defined
bool defined() const
Check if this pipeline object is defined.
Halide::Pipeline::RealizationArg::size
size_t size() const
Definition: Pipeline.h:129
Halide::Func
A halide function.
Definition: Func.h:667
Halide::Pipeline::compile_to_llvm_assembly
void compile_to_llvm_assembly(const std::string &filename, const std::vector< Argument > &args, const std::string &fn_name, const Target &target=get_target_from_environment())
Statically compile a pipeline to llvm assembly, with the given filename (which should probably end in...
Halide::Internal::IRMutator
A base class for passes over the IR which modify it (e.g.
Definition: IRMutator.h:24
Halide::AutoSchedulerResults::featurization
std::vector< uint8_t > featurization
Definition: Pipeline.h:88
HALIDE_NO_USER_CODE_INLINE
#define HALIDE_NO_USER_CODE_INLINE
Definition: Util.h:44
Halide::ExternSignature::ExternSignature
ExternSignature()=default
Halide::Pipeline::set_custom_do_task
void set_custom_do_task(int(*custom_do_task)(void *, int(*)(void *, int, uint8_t *), int, uint8_t *))
Set a custom task handler to be called by the parallel for loop.
Halide::Pipeline::set_custom_trace
void set_custom_trace(int(*trace_fn)(void *, const halide_trace_event_t *))
Set custom routines to call when tracing is enabled.
Halide::MachineParams::generic
static MachineParams generic()
Default machine parameters for generic CPU architecture.
dst
char * dst
Definition: printer.h:32
Halide::Pipeline::set_error_handler
void set_error_handler(void(*handler)(void *, const char *))
Set the error handler function that be called in the case of runtime errors during halide pipelines.
Halide::Pipeline::add_custom_lowering_pass
void add_custom_lowering_pass(T *pass)
Add a custom pass to be used during lowering.
Definition: Pipeline.h:468
Halide::ExternSignature
Definition: Pipeline.h:582
free
void free(void *)
Halide::Pipeline::print_loop_nest
void print_loop_nest()
Write out the loop nests specified by the schedule for this Pipeline's Funcs.
Halide::Pipeline::trace_pipeline
void trace_pipeline()
Generate begin_pipeline and end_pipeline tracing calls for this pipeline.
halide_buffer_t
The raw representation of an image passed around by generated Halide code.
Definition: HalideRuntime.h:1404
Halide::ExternCFunction::signature
const ExternSignature & signature() const
Definition: Pipeline.h:656
Halide::MachineParams::balance
float balance
Indicates how much more expensive is the cost of a load compared to the cost of an arithmetic operati...
Definition: Pipeline.h:38
Halide::ExternSignature::ExternSignature
ExternSignature(const Type &ret_type, bool is_void_return, const std::vector< Type > &arg_types)
Definition: Pipeline.h:591
Halide::get_jit_target_from_environment
Target get_jit_target_from_environment()
Return the target that Halide will use for jit-compilation.
Halide::Realization::size
size_t size() const
The number of images in the Realization.
Halide::Runtime::Internal::custom_do_task
WEAK halide_do_task_t custom_do_task
Definition: thread_pool_common.h:548
Halide::JITExtern::extern_c_function
const ExternCFunction & extern_c_function() const
Definition: Pipeline.h:681
Halide::AutoSchedulerResults::target
Target target
Definition: Pipeline.h:85
Halide::type_of
Type type_of()
Construct the halide equivalent of a C type.
Definition: Type.h:503
Halide::Pipeline::compile_to_c
void compile_to_c(const std::string &filename, const std::vector< Argument > &, const std::string &fn_name, const Target &target=get_target_from_environment())
Statically compile a pipeline to C source code.
Halide::Expr
A fragment of Halide syntax.
Definition: Expr.h:256
Halide::Pipeline::compile_to_multitarget_object_files
void compile_to_multitarget_object_files(const std::string &filename_prefix, const std::vector< Argument > &args, const std::vector< Target > &targets, const std::vector< std::string > &suffixes)
Like compile_to_multitarget_static_library(), except that the object files are all output as object f...
Halide::Realization
A Realization is a vector of references to existing Buffer objects.
Definition: Realization.h:21
Halide::ExternSignature::ret_type
const Type & ret_type() const
Definition: Pipeline.h:605
Halide::JITExtern::pipeline
const Pipeline & pipeline() const
Definition: Pipeline.h:678
Module.h
Halide::Pipeline::outputs
std::vector< Func > outputs() const
Get the Funcs this pipeline outputs.
Halide::AutoSchedulerResults
Definition: Pipeline.h:83
IntrusivePtr.h
Halide::Pipeline::get_func
Func get_func(size_t index)
Return handle to the index-th Func within the pipeline based on the topological order.
Halide::ExternCFunction::ExternCFunction
ExternCFunction(RT(*f)(Args... args))
Definition: Pipeline.h:649
Halide::Runtime::Internal::custom_do_par_for
WEAK halide_do_par_for_t custom_do_par_for
Definition: thread_pool_common.h:550
Halide::Pipeline::custom_lowering_passes
const std::vector< CustomLoweringPass > & custom_lowering_passes()
Get the custom lowering passes.
Realization.h
user_context
void * user_context
Definition: printer.h:33
Halide::Target
A struct representing a target machine and os to generate code for.
Definition: Target.h:19
Halide::Pipeline::compile_jit
void compile_jit(const Target &target=get_jit_target_from_environment())
Eagerly jit compile the function to machine code.
Halide::LinkageType::ExternalPlusMetadata
@ ExternalPlusMetadata
Visible externally. Argument metadata and an argv wrapper are also generated.
Halide::ExternSignature::is_void_return
bool is_void_return() const
Definition: Pipeline.h:610
Halide::JITExtern
Definition: Pipeline.h:661
Halide::Pipeline::get_jit_externs
const std::map< std::string, JITExtern > & get_jit_externs()
Return the map of previously installed externs.
Halide::ExternSignature::operator<<
friend std::ostream & operator<<(std::ostream &stream, const ExternSignature &sig)
Definition: Pipeline.h:618
Halide::Pipeline::jit_handlers
const Internal::JITHandlers & jit_handlers()
Get a struct containing the currently set custom functions used by JIT.
Halide::ParamMap::empty_map
static const ParamMap & empty_map()
A const ref to an empty ParamMap.
Definition: ParamMap.h:108
Halide::Pipeline::set_custom_allocator
void set_custom_allocator(void *(*malloc)(void *, size_t), void(*free)(void *, void *))
Set a custom malloc and free for halide to use.