Error with Torch.jl

Hello,

I am new using Julia. Currently, I am implementing a very simple example with Flux and Torch.jl, and I get the following error: getindex not defined for Tensor{Float32,2}. The code is the following:

using Flux
using Flux: params, update!, Losses
using CUDA
using Dates: now
using Statistics: mean
using Random
using Torch
using Torch: torch

if CUDA.has_cuda_gpu()
    #device = gpu;
    device = torch;
    println("Training on GPU")
    println(" - CUDA version: $(CUDA.version())")
    println(" - Device: $(CUDA.name(CUDA.CuDevice(0)))")
else
    device = cpu;
    println("Training on CPU")
end

model = Chain(
    Dense(10, 128, relu),
    Dense(128, 128, relu),
    Dense(128, 1)
) |> device

p = params(model)

opt = ADAM(3e-4)

x = rand(Float32, 10, 2000) |> device
y = rand(Float32, 1, 2000) |> device

function loss(x, y)
    ŷ = model(x)
    return Losses.mse(ŷ, y; agg=mean)
end

for j = 1:10
    st = now()
    for i = 1:10
        g = gradient(() -> loss(x, y), p)
        update!(opt, p, g)
    end
    println(now() - st)
end

My system information is this:

Julia Version 1.5.1
Commit 697e782ab8 (2020-08-25 20:08 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Xeon(R) CPU @ 2.20GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-9.0.1 (ORCJIT, broadwell)
Environment:
  JULIA_NUM_THREADS = 4

My GPU info is:

CUDA version: 10.1.0
Device: Tesla T4

Packages info:

CUDA v2.3.0
Flux v0.11.2
IJulia v1.23.1
Torch v0.1.2

Thanks.

Can you post a full stacktrace? It’s likely that some higher-level operation isn’t implemented and thus falling back to a getindex method not supported by Torch.jl.

Sorry, but I don’t know how to do a full stacktrace. Could you tell me how to do it?

Thank you very much.

The stacktrace is the error output that came with the message you posted. It’ll look like any backtrace you’ve seen from Python. e.g:

julia> 1 + "s"
ERROR: MethodError: no method matching +(::Int64, ::String)
Closest candidates are:
  +(::Any, ::Any, ::Any, ::Any...) at operators.jl:538
  +(::T, ::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} at int.jl:86
  +(::Union{Int16, Int32, Int64, Int8}, ::BigInt) at gmp.jl:531
  ...
Stacktrace:
 [1] top-level scope at REPL[5]:1

Thanks, and sorry for my ignorance. The stacktrace is the following:

getindex not defined for Tensor{Float32,2}

Stacktrace:
 [1] error(::String, ::Type{T} where T) at ./error.jl:42
 [2] error_if_canonical_getindex(::IndexCartesian, ::Tensor{Float32,2}, ::Int64, ::Int64) at ./abstractarray.jl:1070
 [3] getindex at ./abstractarray.jl:1059 [inlined]
 [4] _getindex at ./abstractarray.jl:1100 [inlined]
 [5] getindex at ./abstractarray.jl:1060 [inlined]
 [6] _broadcast_getindex at ./broadcast.jl:614 [inlined]
 [7] _getindex at ./broadcast.jl:644 [inlined] (repeats 2 times)
 [8] _broadcast_getindex at ./broadcast.jl:620 [inlined]
 [9] getindex(::Base.Broadcast.Broadcasted{Nothing,Tuple{Base.OneTo{Int64},Base.OneTo{Int64}},typeof(Base.literal_pow),Tuple{Base.RefValue{typeof(^)},Base.Broadcast.Extruded{Tensor{Float32,2},Tuple{Bool,Bool},Tuple{Int64,Int64}},Base.RefValue{Val{2}}}}, ::CartesianIndex{2}) at ./broadcast.jl:575
 [10] macro expansion at ./broadcast.jl:932 [inlined]
 [11] macro expansion at ./simdloop.jl:77 [inlined]
 [12] copyto! at ./broadcast.jl:931 [inlined]
 [13] copyto!(::Array{Float32,2}, ::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{2},Tuple{Base.OneTo{Int64},Base.OneTo{Int64}},typeof(Base.literal_pow),Tuple{Base.RefValue{typeof(^)},Tensor{Float32,2},Base.RefValue{Val{2}}}}) at ./broadcast.jl:886
 [14] copy at ./broadcast.jl:862 [inlined]
 [15] materialize at ./broadcast.jl:837 [inlined]
 [16] adjoint at /root/.julia/packages/Zygote/Iz3wR/src/lib/broadcast.jl:85 [inlined]
 [17] _pullback at /root/.julia/packages/ZygoteRules/OjfTt/src/adjoint.jl:57 [inlined]
 [18] #mse#6 at /root/.julia/packages/Flux/mVj29/src/losses/functions.jl:17 [inlined]
 [19] _pullback(::Zygote.Context, ::Flux.Losses.var"##mse#6", ::typeof(mean), ::typeof(Flux.Losses.mse), ::Tensor{Float32,2}, ::Tensor{Float32,2}) at /root/.julia/packages/Zygote/Iz3wR/src/compiler/interface2.jl:0 (repeats 2 times)
 [20] loss at ./In[4]:16 [inlined]
 [21] _pullback(::Zygote.Context, ::typeof(loss), ::Tensor{Float32,2}, ::Tensor{Float32,2}) at /root/.julia/packages/Zygote/Iz3wR/src/compiler/interface2.jl:0
 [22] #1 at ./In[5]:4 [inlined]
 [23] _pullback(::Zygote.Context, ::var"#1#2") at /root/.julia/packages/Zygote/Iz3wR/src/compiler/interface2.jl:0
 [24] pullback(::Function, ::Zygote.Params) at /root/.julia/packages/Zygote/Iz3wR/src/compiler/interface.jl:167
 [25] gradient(::Function, ::Zygote.Params) at /root/.julia/packages/Zygote/Iz3wR/src/compiler/interface.jl:48
 [26] top-level scope at In[5]:4
 [27] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091

Looks like Flux.mse is triggering some broadcast machinery that Torch.jl doesn’t implement. I would strongly recommend using normal Flux with CUDA.jl if you’re new to Julia in general. Torch.jl is very much an experimental library with many, many gaps in the API. The only benefit it has over Flux/CUDA is performance in a select few operations.

I just wanted to check how the performance was improved using Torch.jl.
Thanks for your help.