Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support vgather with all Int types #98

Open
davidbp opened this issue Sep 2, 2022 · 1 comment
Open

Support vgather with all Int types #98

davidbp opened this issue Sep 2, 2022 · 1 comment

Comments

@davidbp
Copy link

davidbp commented Sep 2, 2022

Hello,

I am building an application that stores a lot of integers with a low integer value (from 1 to 64 at most). I wanted to leverage this package to load in SIMD chunks the integers. My problem is that when I want to use those chunks as indices in the form Vec{N,Int32} or Vec{N,UInt8} then vgather it is not working.

Problem: It seems vgather only works with Int64

MWE

The following code works:

reals = rand(32);
idx = rand(1:32, 1000);
idx_slice_int64 = vload(Vec{4,Int64}, idx, 1)
vgather(reals, idx_slice_int64)

But the same code with Int32 (or other Int element types) does not work

reals = rand(32);
idx = Int32.(rand(1:32, 1000));
idx_slice_int32 = vload(Vec{4,Int32}, idx, 1)
vgather(reals, idx_slice_int32)
MethodError: no method matching vgather(::Vector{Float64}, ::Vec{4, Int32})
Closest candidates are:
  vgather(::Union{Base.ReinterpretArray{T, 1, T2, A} where {T2, A<:Union{DenseVector{T2}, SubArray{T2, 1, P, I, true} where {P, I<:Union{Tuple{Vararg{Real}}, Tuple{AbstractUnitRange, Vararg{Any}}}}}}, SubArray{T, 1, P, I, true} where {P, I<:Union{Tuple{Vararg{Real}}, Tuple{AbstractUnitRange, Vararg{Any}}}}, DenseVector{T}}, ::Vec{N, Int64}) where {N, T<:Union{Float32, Float64, Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}} at ~/.julia/packages/SIMD/myoU9/src/arrayops.jl:157
  vgather(::Union{Base.ReinterpretArray{T, 1, T2, A} where {T2, A<:Union{DenseVector{T2}, SubArray{T2, 1, P, I, true} where {P, I<:Union{Tuple{Vararg{Real}}, Tuple{AbstractUnitRange, Vararg{Any}}}}}}, SubArray{T, 1, P, I, true} where {P, I<:Union{Tuple{Vararg{Real}}, Tuple{AbstractUnitRange, Vararg{Any}}}}, DenseVector{T}}, ::Vec{N, Int64}, ::Vec{N, Bool}) where {N, T<:Union{Float32, Float64, Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}} at ~/.julia/packages/SIMD/myoU9/src/arrayops.jl:157
  vgather(::Union{Base.ReinterpretArray{T, 1, T2, A} where {T2, A<:Union{DenseVector{T2}, SubArray{T2, 1, P, I, true} where {P, I<:Union{Tuple{Vararg{Real}}, Tuple{AbstractUnitRange, Vararg{Any}}}}}}, SubArray{T, 1, P, I, true} where {P, I<:Union{Tuple{Vararg{Real}}, Tuple{AbstractUnitRange, Vararg{Any}}}}, DenseVector{T}}, ::Vec{N, Int64}, ::Vec{N, Bool}, ::Val{Aligned}) where {N, T<:Union{Float32, Float64, Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}, Aligned} at ~/.julia/packages/SIMD/myoU9/src/arrayops.jl:157

Stacktrace:
 [1] top-level scope
   @ In[49]:4
 [2] eval
   @ ./boot.jl:368 [inlined]
 [3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
   @ Base ./loading.jl:1428

This makes me use much more memory than I would like storing the indices from which I load in idx_slice to an unreasonable Int type (for the amount of reals I might be gathering from).

@davidbp davidbp changed the title Support gather with all Int types Support vgather with all Int types Sep 2, 2022
@davidbp
Copy link
Author

davidbp commented Mar 28, 2023

Looking a bit on vgather it seems the Vec eltypes for the indices are required to be Int64 since idx::Vec{N, Int} in

@propagate_inbounds function vgather(a::FastContiguousArray{T,1}, idx::Vec{N, Int},
                                     mask::Vec{N,Bool}=one(Vec{N,Bool}),
                                     ::Val{Aligned}=Val(false)) where {N, T<:ScalarTypes, Aligned}
    @boundscheck for i in 1:N
        checkbounds(a, @inbounds idx[i])
    end
    GC.@preserve a begin
        ptrs = _get_vec_pointers(a, idx)
        return vgather(ptrs, mask, Val(Aligned))
    end
end

But it seems possible to allow idx::Vec{N, <:Integer}.

I tried to update _get_vec_pointers and vgather as follows

@inline function _get_vec_pointers(a, idx::Vec{N, I}) where {N, I<:Integer}
    ptrs = pointer(a) + (idx - 1) * sizeof(eltype(a))
end

@propagate_inbounds function vgather(a::FastContiguousArray{T,1}, idx::Vec{N, I},
                                     mask::Vec{N,Bool}=one(Vec{N,Bool}),
                                     ::Val{Aligned}=Val(false)) where {N, T<:ScalarTypes,  I<:Integer, Aligned}
    @boundscheck for i in 1:N
        checkbounds(a, @inbounds idx[i])
    end
    GC.@preserve a begin
        ptrs = _get_vec_pointers(a, idx)
        return vgather(ptrs, mask, Val(Aligned))
    end
end

But then I get

MethodError: no method matching sext(::Type{NTuple{4, VecElement{Ptr{Float64}}}}, ::NTuple{4, VecElement{Int32}})

And I am kind of lost here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant