FluxML / Torch.jl

Sensible extensions for exposing torch in Julia.
Other
213 stars 15 forks source link

getindex not defined for Tensor{Float32,4} #7

Closed gartangh closed 4 years ago

gartangh commented 4 years ago

@dhairyagandhi96 , need to be able to slice a Tensor{Float32,4} into smaller tensors, so I came up with the following piece of code as MWE:

using CuArrays
using Torch

ip = rand(Float32, 10, 10, 4, 1);
ip[:,:,1,1]

tip = tensor(ip, dev = 0);
tip[:,:,1,1]

But the last line gives the following error:

ERROR: LoadError: getindex not defined for Tensor{Float32,4}

I see that you commented out the following lines of code: https://github.com/dhairyagandhi96/Torch.jl/blob/d7471fa831117c685a3f310b32716c9f8a6ccd2f/src/tensor.jl#L84

Would it be much work to get slicing working for tensors?

DhairyaLGandhi commented 4 years ago

We should just overload view to use atg_view for Tensors here.

gartangh commented 4 years ago

@dhairyagandhi96 , I tried this with the following:

using Torch

# function atg_view(arg1, self, size_data, size_len)
#     @runtime_error_check ccall((:atg_view, :libdoeye_caml), Cint, (Ptr{tensor}, tensor, Ptr{Int64}, Cint), arg1, self, size_data, size_len)
# end

function Base.view(t::Tensor{T,N}, sz::Vararg{Any,N}) where {T,N}
  ptr = Ref(Ptr{Cvoid}())

  sz = reverse(collect(sz))
  d = Ref(pointer(sz))
  len = length(sz)

  Torch.atg_view(ptr, t.ptr, d.x, len)
  Tensor{T,N}(ptr[], on(t))
end

ip = rand(Float32, 10, 10, 4, 1);
tip = tensor(ip, dev = 0);
# top = tip[:,:,1:2,1];
top12 = view(tip, :, :, 1:2, 1);
top34 = view(tip, :, :, 3:4, 1);

but that does not work. The error is:

ERROR: LoadError: "shape '[140032159060064, 140031141444432, 140032253631264, 140032253631264]' is invalid for input of size 400"

where the large numbers are the addresses of the colons, the range 1:2 and the integer 1.

When I try this with top1111 = view(tip, 1, 1, 1, 1);, the error makes more sense:

ERROR: LoadError: "shape '[1, 1, 1, 1]' is invalid for input of size 400"

So my question is: does atg_view support slicing using colons and ranges? Or am I missing something here?

DhairyaLGandhi commented 4 years ago

Right, so there are a couple things here, the indices need to be translated to the correct ones that torch expects. This means that the colons need to be translated accordingly to the actual index values. Also, are you trying to set into a Tensor?

gartangh commented 4 years ago

Does atg_view correspond to torch.Tensor.view() ? Because that would return a view over the whole tensor with a new shape. I really need to slice the tensor into pieces.

I think atg_index_select/torch.Tensorl.index_select() or atg_chunk/torch.chunk() might do the job for me, as I only have to slice over 1 dimension.

gartangh commented 4 years ago

I feel like I'm almost there with atg_chunk:

using Torch

# function atg_chunk(op::AbstractVector, self, chunks, dim)
#     @runtime_error_check ccall((:atg_chunk, :libdoeye_caml), Cint, (Ptr{tensor}, tensor, Int64, Int64), op, self, chunks, dim)
# end

function chunk(t::Tensor{Float32,4}, chunks::Int64)
  vtop::AbstractVector{Tensor{Float32,4}} = []
  dim::Int64 = 2 # indexing starts att 0 now

  Torch.atg_chunk(vtop, t.ptr, chunks, dim)

  return vtop
end

ip   = rand(Float32, 10, 10, 4, 1);
tip  = tensor(ip, dev = 0);
vtop = chunk(tip, 2);

There are no errors when calling Torch.atg_chunk(), so the arguments should be from the correct type. Still vtop remains empty, while I expected it to become populated with the chunks (2 tensors of type Tensor{Float32,4} and dimensions (10,10,2,1)).

I'm quite confused with the declaration of atg_chunk in libdoeye_caml_generated.jl. So the arguments it takes are: op::AbstractVector, self, chunks, dim, but then further, it uses (Ptr{tensor}, tensor, Int64, Int64), op, self, chunks, dim.

DhairyaLGandhi commented 4 years ago

I think vtop internally would actually be populated like a pointer corresponding to a Tensor{Tensor}

You can take a look at the broadcast definition on how that is handled

DhairyaLGandhi commented 4 years ago

Does atg_view correspond to torch.Tensor.view()

Yes

gartangh commented 4 years ago

You can take a look at the broadcast definition on how that is handled

Where can I find that definition exactly?

DhairyaLGandhi commented 4 years ago

Maybe I haven't committed it yet, the basic flow is like

julia> n = [Ptr{Cvoid}() for _ in 1:2]
2-element Array{Ptr{Nothing},1}:
 Ptr{Nothing} @0x0000000000000000
 Ptr{Nothing} @0x0000000000000000

julia> ts = [tip.ptr,tip.ptr]
2-element Array{CuPtr{Float32},1}:
 CuPtr{Float32}(0x000000002847ce80)
 CuPtr{Float32}(0x000000002847ce80)

julia> Torch.atg_broadcast_tensors(n, ts, length(ts))

julia> n
2-element Array{Ptr{Nothing},1}:
 Ptr{Nothing} @0x00000000286e5840
 Ptr{Nothing} @0x000000002867e3f0

Hopefully this makes sense

gartangh commented 4 years ago

I got it working with the following:

function chunk(t::Tensor{Float32,4}, chunks::Int64)
  # n = [Ptr{Cvoid}() for _ in 1:chunks]
  dim::Int64 = 1 # reversed indexing and starting at 0
  ts = [t.ptr for _ in 1:chunks]

  Torch.atg_chunk(ts, t.ptr, chunks, dim)
  # Torch.atg_broadcast_tensors(n, ts, chunks)

  vtop::Vector{Tensor{Float32,4}} = [t for _ in 1:chunks]
  for i in 1:chunks
    vtop[i] = Tensor{Float32,4}(ts[i], Torch.on(t))
  end

  return vtop
end

Thank you so much for your help @dhairyagandhi96 !

DhairyaLGandhi commented 4 years ago

A PR to add that would be super useful too!

kadir-gunel commented 3 years ago

Hello,

I am getting the below error message while calculating the gradients of the ResNet example in the readme :

gradient(x -> sum(tresnet(x)), tip)

(Float32[Error showing value of type Tuple{Tensor{Float32,4}}:
ERROR: getindex not defined for Tensor{Float32,4}

What should I do ?

B.R.

DhairyaLGandhi commented 3 years ago

That's because we need a way to display the tensors as compressed objects. If you don't need the values you can add a semicolon at the end to suppress the printing.

kadir-gunel commented 3 years ago

Oh I see now. I thought it was having trouble while taking the derivatives. Thank you