g on the left-hand side of an assignment) 

Note that these cases may in fact be traceable in the future.

####  Automatic Trace Checking  ¶

One way to automatically catch many errors in traces is by using `
check_inputs  ` on the ` torch.jit.trace()  ` API. ` check_inputs  ` takes a
list of tuples of inputs that will be used to re-trace the computation and
verify the results. For example:

    
    
    def loop_in_traced_fn(x):
        result = x[0]
        for i in range(x.size(0)):
            result = result * x[i]
        return result
    
    inputs = (torch.rand(3, 4, 5),)
    check_inputs = [(torch.rand(4, 5, 6),), (torch.rand(2, 3, 4),)]
    
    traced = torch.jit.trace(loop_in_traced_fn, inputs, check_inputs=check_inputs)
    

Gives us the following diagnostic information:

    
    
    ERROR: Graphs differed across invocations!
    Graph diff:
    
                graph(%x : Tensor) {
                %1 : int = prim::Constant[value=0]()
                %2 : int = prim::Constant[value=0]()
                %result.1 : Tensor = aten::select(%x, %1, %2)
                %4 : int = prim::Constant[value=0]()
                %5 : int = prim::Constant[value=0]()
                %6 : Tensor = aten::select(%x, %4, %5)
                %result.2 : Tensor = aten::mul(%result.1, %6)
                %8 : int = prim::Constant[value=0]()
                %9 : int = prim::Constant[value=1]()
                %10 : Tensor = aten::select(%x, %8, %9)
            -   %result : Tensor = aten::mul(%result.2, %10)
            +   %result.3 : Tensor = aten::mul(%result.2, %10)
            ?          ++
                %12 : int = prim::Constant[value=0]()
                %13 : int = prim::Constant[value=2]()
                %14 : Tensor = aten::select(%x, %12, %13)
            +   %result : Tensor = aten::mul(%result.3, %14)
            +   %16 : int = prim::Constant[value=0]()
            +   %17 : int = prim::Constant[value=3]()
            +   %18 : Tensor = aten::select(%x, %16, %17)
            -   %15 : Tensor = aten::mul(%result, %14)
            ?     ^                                 ^
            +   %19 : Tensor = aten::mul(%result, %18)
            ?     ^                                 ^
            -   return (%15);
            ?             ^
            +   return (%19);
            ?             ^
                }
    

This message indicates to us that the computation differed between when we
first traced it and when we traced it with the ` check_inputs  ` . Indeed, the
loop within the body of ` loop_in_traced_fn  ` depends on the shape of the
input ` x  ` , and thus when we try another ` x  ` with a different shape, the
trace differs.

In this case, data-dependent control flow like this can be captured using [ `
torch.jit.script()  ` ](generated/torch.jit.script.html#torch.jit.script
"torch.jit.script") instead:

    
    
    def fn(x):
        result = x[0]
        for i in range(x.size(0)):
            result = result * x[i]
        return result
    
    inputs = (torch.rand(3, 4, 5),)
    check_inputs = [(torch.rand(4, 5, 6),), (torch.rand(2, 3, 4),)]
    
    scripted_fn = torch.jit.script(fn)
    print(scripted_fn.graph)
    #print(str(scripted_fn.graph).strip())
    
    for input_tuple in [inputs] + check_inputs:
        torch.testing.assert_allclose(fn(*input_tuple), scripted_fn(*input_tuple))
    

Which produces:

    
    
    graph(%x : Tensor) {
        %5 : bool = prim::Constant[value=1]()
        %1 : int = prim::Constant[value=0]()
        %result.1 : Tensor = aten::select(%x, %1, %1)
        %4 : int = aten::size(%x, %1)
        %result : Tensor = prim::Loop(%4, %5, %result.1)
        block0(%i : int, %7 : Tensor) {
            %10 : Tensor = aten::select(%x, %1, %i)
            %result.2 : Tensor = aten::mul(%7, %10)
            -> (%5, %result.2)
        }
        return (%result);
    }
    

####  Tracer Warnings  ¶

The tracer produces warnings for several problematic patterns in traced
computa