I am trying to understand how to use SIMD.jl.
After trying the vadd! example in the documentation I wanted use SIMD in a different example. No success so far.

This is what I would like to simdify:

function myfunc(a, b)
if a > b
return a - b
else
return a + b
end
end
x = rand(1_000_000);
# do myfunc.(x, 2.) with explicit simd calls
myfunc.(x, 2.)

I tried the following

function myfunc_simd(x::Vector{T}, value::T, ::Type{Vec{N,T}}) where {N, T}
@assert length(x) % N == 0
result = Array{T}(undef, length(x))
lane = VecRange{N}(0)
@inbounds for i in 1:N:length(x)
result[lane + i] += x[lane+i] > value ? x[k+lane] - value : x[k+lane] +value
end
end

But I gon an error

x = rand(Float32,1_000_000);
myfunc_simd(x, Float32(2.), Vec{8,Float32})
TypeError: non-boolean (Vec{8,Bool}) used in boolean context

Any ideas on how to do something like this?

Do you know about any tutorial containing examples using SIMD.jl ?

I have seen https://kristofferc.github.io/post/intrinsics/ , which is pretty awesome, but does not contain any example with â€śflag-boolean vectorsâ€ť (masks) used to control an if-else statement like the one I have here.

julia> function myfunc_simd(x::Vector{T}, value::T, ::Type{Vec{N,T}}) where {N, T}
@assert length(x) % N == 0
result = Array{T}(undef, length(x))
lane = VecRange{N}(0)
@inbounds for i in 1:N:length(x)
x_vslice = vload(Vec{N, T}, x, i) # i = 2*k+1 where k=1,2,3,4,...
result[lane + i] = vifelse(x_vslice > 2, x_vslice - value, x_vslice + value)
end
return result
end
myfunc_simd (generic function with 1 method)

Using the vifelse I managed to do the function that does what I want

I think thatâ€™s whatâ€™s happening in this case. In the code_llvm for broadcast(myfunc, x, 1), there are already occurrences of <8 x float>, and the native code uses ymm registers and vblendvps masked SIMD instructions.