EnzymeAD / Enzyme.jl

Julia bindings for the Enzyme automatic differentiator
https://enzyme.mit.edu
MIT License
455 stars 63 forks source link

Crashes with BandedMatrices.jl #117

Closed dlfivefifty closed 3 years ago

dlfivefifty commented 3 years ago

I'm looking for a reverse mode autodiff package that supports in-place mutation and @ChrisRackauckas suggested this. Unfortunately it crashed on first attempt:

julia> using FillArrays, BandedMatrices, Enzyme

julia> f = x -> BandedMatrix(0 => Fill(x^2,10))[1,1]
#1 (generic function with 1 method)

julia> f(0.1)
0.010000000000000002

julia> autodiff(f, Active(0.1))
mod: ; ModuleID = 'text'
source_filename = "text"
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:10:11:12:13"
target triple = "x86_64-apple-darwin20.4.0"

@_j_const1 = private unnamed_addr constant [2 x i64] [i64 10, i64 10]
@_j_const2 = private unnamed_addr constant [2 x i64] zeroinitializer
@exception.38 = private unnamed_addr constant [10 x i8] c"exception\00", align 1
@exception.44 = private unnamed_addr constant [13 x i8] c"bounds error\00", align 1

define internal fastcc nonnull {} addrspace(10)* @julia_dec_1477(i64 zeroext %0, i8 zeroext %1) unnamed_addr !dbg !65 {
top:
  %2 = call {}*** @julia.ptls_states()
  %3 = call fastcc i64 @julia_ndigits0zpb_1459(i64 zeroext %0), !dbg !67
  %.not = icmp slt i64 %3, 1, !dbg !74
  %4 = select i1 %.not, i64 1, i64 %3, !dbg !77
  %5 = and i8 %1, 1, !dbg !80
  %6 = zext i8 %5 to i64, !dbg !80
  %7 = add i64 %4, %6, !dbg !91
  %8 = icmp sgt i64 %7, -1, !dbg !93
  br i1 %8, label %L33, label %L25, !dbg !95

L25:                                              ; preds = %top
  %9 = call fastcc nonnull {} addrspace(10)* @julia_throw_inexacterror_1461(i64 signext %7) #6, !dbg !95
  unreachable, !dbg !95

L33:                                              ; preds = %top
  %10 = call nonnull {} addrspace(10)* @jl_alloc_string(i64 %7), !dbg !105
  %11 = call nonnull {} addrspace(10)* @jl_string_to_array({} addrspace(10)* nonnull %10), !dbg !112
  %12 = icmp slt i64 %7, 2, !dbg !114
  br i1 %12, label %L56, label %pass.lr.ph, !dbg !119
ChrisRackauckas commented 3 years ago

Is this calling into OpenBLAS?

dlfivefifty commented 3 years ago

Shouldn't be: it's not doing anything other than calling getindex

wsmoses commented 3 years ago

Can you attach the entire log as a file? My guess here is that there's a julia runtime call such as jl_string_to_array that we didn't add a handler for yet and I'd be curious which it was.

dlfivefifty commented 3 years ago

Here's the full log.

Enzyme.txt

wsmoses commented 3 years ago

Yup looks like the culprit here is jl_object_id_ which should be an easy fix as simply marking it as inactive (or alternatively marking it as returning an integer/readonly for activity analysis itself to determine this).

There may be a couple of other things here as well, which I'll take a look at shortly.

wsmoses commented 3 years ago

The patch available in the obj branch solves the immediate problem, but this eventually hits a GC error [presumably can be solved by proper GC integration which is planned, but not yet available].

cc @vchuravy

Illegal address space cast from decayed ptr
      %9 = addrspacecast double addrspace(11)* %8 to double*

signal (6): Aborted
in expression starting at /mnt/Data/git/Enzyme.jl/band.jl:4
gsignal at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
abort at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
runOnFunction at /mnt/Data/git/Enzyme.jl/julia/src/llvm-gc-invariant-verifier.cpp:183
dlfivefifty commented 3 years ago

OK... I guess I can wait.

I'm hoping to eventually do reverse-mode auto diff with banded matrices for diff eqs, e.g., Schrödinger equation... since linear algebra implementations are in-place I believe I need to wait for this package.

wsmoses commented 3 years ago

After latest update, remaining minimal erroring example (incorrect but runs):

using Enzyme
Enzyme.API.printall!(true)

function bmat(x)
    # data = [x]
    data = zeros(Float64, 1, 1)
    @inbounds data[1] = x
    return data
end

function f(x::Float64)
    @inbounds return bmat(x)[1]
end
@show f(0.1)
Enzyme.API.printall!(true)
@show autodiff(f, Active(0.1))