Skip to content
Andrew Adams edited this page Nov 19, 2015 · 19 revisions

Debugging inferred function bounds

HL_TRACE=1 prints out the boundaries of all realizations of Funcs. (Inlined Funcs don't really have boundaries.)

Higher values of HL_TRACE start to print the loads and stores too.

You can also call Func::trace_realizations to get a printf that displays the boundaries for a particular func.

Inspecting the value of an Expr at runtime

You can wrap a print around an Expr to print its value at runtime, e.g say you think b is taking on bad values in the following Func definition:

f(x) = a + b;

You could rewrite this to:

f(x) = a + print(b, " <- b has this value when x is ", x);

print returns the first argument, and prints all the arguments as a side-effect. The arguments may be of type Expr, std::string, const char *, int, or float.

You can also conditionally print:

f(x) = a + print_when(b < 0, b, " b was not supposed to be negative! It happened at x = ", x);

print_when returns the second argument. When the first argument is true, it prints all the other arguments as a side-effect.

Understanding a schedule

You can use Func::compile_to_lowered_stmt to compile a Halide pipeline to human-readable imperative psuedo-code that includes all the effects of scheduling. E.g:

#include <Halide.h>

using namespace Halide;

int main(int argc, char **argv) {
    Func f;
    Var x, y;
    f(x, y) = x+y;
    f.vectorize(x, 4).unroll(x, 2).parallel(y);
    f.compile_to_lowered_stmt("f.html", HTML);

    return 0;
}

produces this output

For a quick look at just the loop nest structure, you can use Func::print_loop_nest. This is used extensively in the tutorials.