ArgumentError: cannot take the CPU address of a CuArray when using selectdim

I’m quite new to Julia computing and even more to GPU computing but I notice that selectdim function from julia output is stored on the CPU acording to this error: “ERROR: ArgumentError: cannot take the CPU address of a CuArray{Float32,2,Nothing}” when running this MWE:

a = CuArrays.rand(3,5)
ERROR: ArgumentError: cannot take the CPU address of a CuArray{Float32,2,Nothing}
 [1] unsafe_convert(::Type{Ptr{Float32}}, ::CuArray{Float32,2,Nothing}) at C:\Users\geoff\.juliapro\JuliaPro_v1.3.1-2\packages\CuArrays\e8PLr\src\array.jl:226
 [2] gemv!(::Char, ::Bool, ::CuArray{Float32,2,Nothing}, ::SubArray{Float32,1,CuArray{Float32,2,Nothing},Tuple{Int64,Base.Slice{Base.OneTo{Int64}}},true}, ::Bool, ::CuArray{Float32,1,Nothing}) at C:\Users\julia\AppData\Local\Julia-1.3.1\share\julia\stdlib\v1.3\LinearAlgebra\src\blas.jl:587
 [3] gemv!(::CuArray{Float32,1,Nothing}, ::Char, ::CuArray{Float32,2,Nothing}, ::SubArray{Float32,1,CuArray{Float32,2,Nothing},Tuple{Int64,Base.Slice{Base.OneTo{Int64}}},true}, ::Bool, ::Bool) at C:\Users\julia\AppData\Local\Julia-1.3.1\share\julia\stdlib\v1.3\LinearAlgebra\src\matmul.jl:463
 [4] mul! at C:\Users\julia\AppData\Local\Julia-1.3.1\share\julia\stdlib\v1.3\LinearAlgebra\src\matmul.jl:66 [inlined]
 [5] mul! at C:\Users\julia\AppData\Local\Julia-1.3.1\share\julia\stdlib\v1.3\LinearAlgebra\src\matmul.jl:203 [inlined]
 [6] *(::CuArray{Float32,2,Nothing}, ::SubArray{Float32,1,CuArray{Float32,2,Nothing},Tuple{Int64,Base.Slice{Base.OneTo{Int64}}},true}) at C:\Users\julia\AppData\Local\Julia-1.3.1\share\julia\stdlib\v1.3\LinearAlgebra\src\matmul.jl:47
 [7] top-level scope at none:0

Has I understand I need to transfert the output of selectdim to GPU as this work:


But I want this part of my code to work on CPU when a is on CPU and to work on GPU otherwise, is this possible ?

Thanks in advance for your help,

I don’t have a great solution, except that using a[1,:] or copy(selectdim(a,1,1)) ought to work on both.

Some views of CuArrays are themselves CuArrays, and many GPU functions demand this type. The fact that yours isn’t is why it’s going to a CPU routine, and the fact that it’s still a StridedArray is why it’s going to a routine which wants a pointer, not a generic fallback (which would give scalar indexing errors instead). Perhaps this could all be done differently but this is the present design.

julia> view(a,1,:) |> typeof  # as in question

julia> view(a,1,:) isa StridedArray

julia> view(a,:,1) |> typeof  # first dimension has stride 1

julia> @which mul!(similar(a, size(a,1)), a, a[1, :], true, false) # GPU method wants all CuArrays 
mul!(Y::CuArray{T,1,P} where P, A::CuArray{T,2,P} where P, B::CuArray{T,1,P} where P, a::Union{Bool, T}, b::Union{Bool, T}) where T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64} in CuArrays.CUBLAS at /Users/me/.julia/dev/CuArrays/src/blas/linalg.jl:95
1 Like

@mcabbott thank you copy() work work just fine ! But for the sake of my understanding of Julia programming do you know why view() return an array on the CPU from an array in the GPU ? I thought that view() doesn’t create new allocation when called.

Right, view makes a view, which internally is (almost always) the SubArray type, and SubArray{Float32,1,CuArray{... indicates the underlying type – it isn’t on the CPU. If you write into this you will change a.

But what’s happening is that * does not end up calling the method designed for CuArrays, and instead falls back to one (of several) intended for CPU arrays, which doesn’t work.

It goes there because signature of the CuArrays mul! method does not allow for SubArray{...,CuArray}. But whether that method could actually handle this case or not, I’m not sure. It’s more difficult than view(a,:,1) because that has stride 1 on the first index (like strides(a) does), and this may be a requirement of the implementation of mul!.

Oh right I get it, many thanks for your explanation !