EnzymeAD / Enzyme.jl

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

Basic SparseMatrixCSC calculations do not work. #1381

Open ToPo-ToPo-ToPo opened 3 months ago

ToPo-ToPo-ToPo commented 3 months ago

I would like to use the basic calculations in SparseMatrixCSC, but they do not work. The following is a simple SparseMatrixCSC-to-SparseMatrixCSC addition program.

using Enzyme
using LinearAlgebra
using SparseArrays
#--------------------------------------------------------------------------------
# Function to be differentiated
#--------------------------------------------------------------------------------
function eval(x::Vector{Float64})
    A = sparse([1, 1, 2, 3], [1, 3, 2, 3], [2.0*x[2]^3.0, 1.0-x[1], 2.0+x[3], -1.0])
    B = sparse([1, 1, 2, 3], [1, 3, 2, 3], [2.0*x[2], 1.0-x[1], 2.0+x[3], -1.0])
    C = A + B
    return C[1, 1] + C[2, 2]
end
#--------------------------------------------------------------------------------
# main
#--------------------------------------------------------------------------------
x = rand(Float64, 3)
dx = [0.0, 0.0, 0.0]

val = eval(x)

# compute gradient
autodiff(Reverse, eval, Duplicated(x, dx))
@show dx 

df_numeric = similar(x)
for i in eachindex(x)
    x_tmp = x[i]
    x_p = copy(x)
    x_p[i] += 1.0e-05
    x_m = copy(x)
    x_m[i] -= 1.0e-05
    df_numeric[i] = (eval(x_p) - eval(x_m)) / (2.0 * 1.0e-05)
end

display(df_numeric)

error = norm(dx-df_numeric)
println("error = $(error)")

The errors that occur when executing the program are as follows:

ERROR: BoundsError: attempt to access 4-element Vector{Int64} at index [0]
Stacktrace:
  [1] _deleteend!
    @ ./array.jl:1081 [inlined]
  [2] resize!
    @ ./array.jl:1320 [inlined]
  [3] trimstorage!
    @ ~/.julia/juliaup/julia-1.10.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:135
  [4] _map_zeropres!
    @ ~/.julia/juliaup/julia-1.10.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:361
  [5] _noshapecheck_map
    @ ~/.julia/juliaup/julia-1.10.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:184
  [6] map
    @ ~/.julia/juliaup/julia-1.10.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:1187 [inlined]
  [7] +
    @ ~/.julia/juliaup/julia-1.10.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/sparsematrix.jl:2242 [inlined]
  [8] eval
    @ ~/my_program/GitHub/JuliaOptOS/tests/Enzyme/sparse_array_tests/basic_add.jl:11 [inlined]
  [9] diffejulia_eval_2011wrap
    @ ~/my_program/GitHub/JuliaOptOS/tests/Enzyme/sparse_array_tests/basic_add.jl:0
 [10] macro expansion
    @ ~/.julia/packages/Enzyme/l4FS0/src/compiler.jl:5378 [inlined]
 [11] enzyme_call
    @ ~/.julia/packages/Enzyme/l4FS0/src/compiler.jl:5056 [inlined]
 [12] CombinedAdjointThunk
    @ ~/.julia/packages/Enzyme/l4FS0/src/compiler.jl:4998 [inlined]
 [13] autodiff
    @ ~/.julia/packages/Enzyme/l4FS0/src/Enzyme.jl:215 [inlined]
 [14] autodiff
    @ ~/.julia/packages/Enzyme/l4FS0/src/Enzyme.jl:238 [inlined]
 [15] autodiff(mode::ReverseMode{false, FFIABI}, f::typeof(eval), args::Duplicated{Vector{Float64}})
    @ Enzyme ~/.julia/packages/Enzyme/l4FS0/src/Enzyme.jl:224
 [16] top-level scope
    @ ~/my_program/GitHub/JuliaOptOS/tests/Enzyme/sparse_array_tests/basic_add.jl:23
wsmoses commented 3 months ago

Should now be fixed on main

ToPo-ToPo-ToPo commented 2 months ago

I have been told that this has been supported, but in my environment, the following error occurred and the calculation could not be performed. Enzyme.jl: Enzyme v0.12.7

┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/kqxyC/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/kqxyC/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/kqxyC/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/kqxyC/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/kqxyC/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/kqxyC/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/kqxyC/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/kqxyC/src/utils.jl:59
ERROR: BoundsError: attempt to access 4-element Vector{Int64} at index [0]
Stacktrace:
  [1] _deleteend!
    @ ./array.jl:1081 [inlined]
  [2] resize!
    @ ./array.jl:1320 [inlined]
  [3] trimstorage!
    @ ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:135
  [4] _map_zeropres!
    @ ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:361
  [5] _noshapecheck_map
    @ ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:184
  [6] map
    @ ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:1187 [inlined]
  [7] +
    @ ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/sparsematrix.jl:2242 [inlined]
  [8] eval
    @ ~/my_program/GitHub/JuliaOptOS/tests/Enzyme/sparse_array_tests/basic_add.jl:11 [inlined]
  [9] diffejulia_eval_6074wrap
    @ ~/my_program/GitHub/JuliaOptOS/tests/Enzyme/sparse_array_tests/basic_add.jl:0
 [10] macro expansion
    @ ~/.julia/packages/Enzyme/UKzrf/src/compiler.jl:5787 [inlined]
 [11] enzyme_call
    @ ~/.julia/packages/Enzyme/UKzrf/src/compiler.jl:5453 [inlined]
 [12] CombinedAdjointThunk
    @ ~/.julia/packages/Enzyme/UKzrf/src/compiler.jl:5332 [inlined]
 [13] autodiff
    @ ~/.julia/packages/Enzyme/UKzrf/src/Enzyme.jl:291 [inlined]
 [14] autodiff
    @ ~/.julia/packages/Enzyme/UKzrf/src/Enzyme.jl:315 [inlined]
 [15] autodiff(mode::ReverseMode{false, FFIABI, false}, f::typeof(eval), args::Duplicated{Vector{Float64}})
    @ Enzyme ~/.julia/packages/Enzyme/UKzrf/src/Enzyme.jl:300
 [16] top-level scope
    @ ~/my_program/GitHub/JuliaOptOS/tests/Enzyme/sparse_array_tests/basic_add.jl:23
wsmoses commented 2 months ago

@ToPo-ToPo-ToPo what is your version of Julia / OS.

The code above works for me on Enzyme#main

wsmoses commented 2 months ago

Also please show the package environments as well

ToPo-ToPo-ToPo commented 1 month ago

I use 1.10.3+0.aarch64.apple.darwin14 (release). The packages used are as follows:

Status `~/.julia/environments/v1.10/Project.toml`
  [6e4b80f9] BenchmarkTools v1.5.0
  [082447d4] ChainRules v1.66.0
  [d360d2e6] ChainRulesCore v1.23.0
  [7da242da] Enzyme v0.12.7
  [95c220a8] ExtendableSparse v1.4.0
  [f6369f11] ForwardDiff v0.10.36
  [42fd0dbc] IterativeSolvers v0.9.4
  [ba0b0d4f] Krylov v0.9.6
  [7ed4a6bd] LinearSolve v2.30.0
  [76087f3c] NLopt v1.0.2
  [b8a86587] NearestNeighbors v0.4.16
  [91a5bcdd] Plots v1.40.4
  [37e2e3b7] ReverseDiff v1.15.3
  [e56a9233] Sparspak v0.3.9
  [64499a7a] WriteVTK v1.19.1
  [e88e6eb3] Zygote v0.6.70
wsmoses commented 1 month ago

Just to double check, since I'm having difficulty reproducing: what happens if you're in an enviroment with only Enzyme.

ToPo-ToPo-ToPo commented 1 month ago

All packages were removed, leaving only Enzyme.jl available. When the same program was run, the error was not resolved.

Enzyme.jl: Enzyme v0.12.8

┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
┌ Warning: TODO reverse jl_array_del_end zero-set used memset rather than runtime type
└ @ Enzyme.Compiler ~/.julia/packages/GPUCompiler/nWT2N/src/utils.jl:59
ERROR: BoundsError: attempt to access 4-element Vector{Int64} at index [0]
Stacktrace:
  [1] _deleteend!
    @ ./array.jl:1081 [inlined]
  [2] resize!
    @ ./array.jl:1320 [inlined]
  [3] trimstorage!
    @ ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:135
  [4] _map_zeropres!
    @ ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:361
  [5] _noshapecheck_map
    @ ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:184
  [6] map
    @ ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/higherorderfns.jl:1187 [inlined]
  [7] +
    @ ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/sparsematrix.jl:2242 [inlined]
  [8] eval
    @ ~/my_program/GitHub/JuliaOptOS/tests/Enzyme/sparse_array_tests/basic_add.jl:11 [inlined]
  [9] diffejulia_eval_2098wrap
    @ ~/my_program/GitHub/JuliaOptOS/tests/Enzyme/sparse_array_tests/basic_add.jl:0
 [10] macro expansion
    @ ~/.julia/packages/Enzyme/UZsMX/src/compiler.jl:5855 [inlined]
 [11] enzyme_call
    @ ~/.julia/packages/Enzyme/UZsMX/src/compiler.jl:5521 [inlined]
 [12] CombinedAdjointThunk
    @ ~/.julia/packages/Enzyme/UZsMX/src/compiler.jl:5400 [inlined]
 [13] autodiff
    @ ~/.julia/packages/Enzyme/UZsMX/src/Enzyme.jl:291 [inlined]
 [14] autodiff
    @ ~/.julia/packages/Enzyme/UZsMX/src/Enzyme.jl:315 [inlined]
 [15] autodiff(mode::ReverseMode{false, FFIABI, false}, f::typeof(eval), args::Duplicated{Vector{Float64}})
    @ Enzyme ~/.julia/packages/Enzyme/UZsMX/src/Enzyme.jl:300
 [16] top-level scope
    @ ~/my_program/GitHub/JuliaOptOS/tests/Enzyme/sparse_array_tests/basic_add.jl:23
wsmoses commented 1 month ago

I tried it out on an arm macbook and it still worked for me:

julia> versioninfo()
Julia Version 1.10.2
Commit bd47eca2c8a (2024-03-01 10:14 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: macOS (arm64-apple-darwin22.4.0)
  CPU: 10 × Apple M1 Max
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, apple-m1)
Threads: 1 default, 0 interactive, 1 GC (on 8 virtual cores)

I'm not really sure how to help more here since I can't reproduce, if you have any ideas.

Perhaps hop on a call or something

ToPo-ToPo-ToPo commented 1 month ago

My environment is as follows. I tried the same version of julia as you, but the error was not resolved. I don't know what is wrong.

julia> versioninfo()
Julia Version 1.10.2
Commit bd47eca2c8a (2024-03-01 10:14 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: macOS (arm64-apple-darwin22.4.0)
  CPU: 8 × Apple M2
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, apple-m1)
Threads: 1 default, 0 interactive, 1 GC (on 4 virtual cores)