Played around with it, a little. On my laptop…
julia> @btime RandV(1,0.01,10)
3.587 ms (23 allocations: 4.75 MiB)
julia> @btime RandV(1,0.01,1000)
3.771 ms (23 allocations: 4.75 MiB)
first version was this…
function RandV2!(ret::Array{Float64}, v, vstep, Num)
# initialization of ret should really be checked, here!!!
vcount = 1
while vcount < Num + 1
limit = round(v / vstep)
candidate = rand(-limit:limit,1,3)
test = candidate[1]^2 + candidate[2]^2 + candidate[3]^2
if abs(sqrt(test) * vstep - v) < 0.01 * v
ret[vcount,:] = candidate .* vstep
vcount += 1
end
end
return ret
end
julia> res = zeros(Float64, 1000, 3) # need some preallocated mem, for all versions, here...
julia> @btime RandV2!(res, 1, 0.01, 10)
17.400 ÎĽs (76 allocations: 5.94 KiB)
julia> @btime RandV2!(res, 1, 0.01, 1_000)
7.022 ms (30054 allocations: 2.29 MiB)
…nice, for small Num, but worse, for larger ones, and also, I didn’t manage to eliminate the allocations.
So then, I fell back to my (much more familiar) procedural - low-level - style and came up with something, that doesn’t look particularly nice, but at least does the job, without allocations…
function RandV3!(ret::Array{Float64}, v, vstep, Num)
# initialization of ret should really be checked, here!!!
vcount = 1
limit = round(v / vstep)
while vcount <= Num
ret[vcount,1] = rand(-limit:limit)
ret[vcount,2] = rand(-limit:limit)
ret[vcount,3] = rand(-limit:limit)
test = ret[vcount,1]^2 + ret[vcount,2]^2 + ret[vcount,3]^2
if abs(sqrt(test) * vstep - v) < 0.01 * v
ret[vcount,1] *= vstep
ret[vcount,2] *= vstep
ret[vcount,3] *= vstep
vcount += 1
end
end
return ret
end
julia> @btime RandV3!(res, 1, 0.01, 10)
38.600 ÎĽs (0 allocations: 0 bytes)
julia> @btime RandV3!(res, 1, 0.01, 1000)
14.684 ms (0 allocations: 0 bytes)
…sadly, despite 0 allocations, performance went down, by ~50%, also.
So now, let’s hope for someone achieving 0 allocations, with great performance, doing all the nice broadcasting and non-low-level - stuff. (Anytime, I used some of that, I ran into allocations, in this example). 