Most Efficient Way to Update and Array/Variable?

Hi all!
First of all, thanks for reading.
I am trying to enhance the performance of this function and I wonder if there is a more Julian way to write it in order to make it faster!

I have 4 variables that I update inside a function ray0 and ray 1 and vectors and Time0 and Time1 are variables.

ray0 gets updated and Time0 recomputed in the while loop, and become ray1 and Time1 is computed. Now, the functions that I call output a new array that I am saving with the corresponding name, and then I rewrite ray0 and Time0 before the next iteration.

Is there a better way to do this?
Thanks for reading!

"This is a function that follows the Um and Thurber Pseudo Pending Algorithm"
function PBUT(ray0::Array{Float64, 2},f::Float64,P::Float64,F_V::Interpolations.GriddedInterpolation{Float64, 3, Float64, Gridded{Linear}, Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}}},F_S::Interpolations.GriddedInterpolation{Float64, 3, Float64, Gridded{Linear}, Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}}})

# First add the central node
ray0=DoublePoints(ray0)
#p=plot(ray0[:,1],ray0[:,3],marker=:circle,yflip=true)
Time0=TravelTime(ray0,F_S);
Time1=copy(Time0);
dT=1;
# Add the necessary nodes & compute Travel Time
while dT>P
ray1=MoveNodes(ray0,f,F_V);
Time1=TravelTime(ray1,F_S);
dT=abs(Time0-Time1);
#plot!(p,ray1[:,1],ray1[:,3],marker=:circle)
#println("Paso1: dT= $dT")
ray0=copy(ray1);
Time0=copy(Time1);
    if dT<=P
        ray0=DoublePoints(ray1);
        Time0=TravelTime(ray0,F_S);
        ray1=MoveNodes(ray0,1.9,F_V);
        Time1=TravelTime(ray1,F_S);
        dT=abs(Time0-Time1);
        #println("Paso2: dT= $dT")
        #plot!(p,ray1[:,1],ray1[:,3],marker=:circle)
        ray0=copy(ray1);
        Time0=copy(Time1);
    end
end
return Time0,ray0
end

If the dimensions do not change, use broadcasting:

ray0 .= ray1

but if ray1 and Time1 are new arrays which are obtained from the corresponding functions, you should also, to get better performance, make those functions operate inplace.

dt changes repeatedly between Int64 and Float64.
You can check type stability using @code_warntype.

Ignoring details like constant vector length, but ray0=DoublePoints(ray0) could possibly be implemented to work in-place: DoublePoints!(ray0), avoiding allocations.

1 Like

Isn’t broadcasting slower than = … I though it was hahaha

How can I do this in-place implementation inside de function?

It mutates in place so it is generally faster than copying and then assigning.

Would be better to have MoveNodes mutate ray0 in-place if possible (or write to a pre-allocated output array, so that you don’t keep allocating new arrays over and over.

Depends on your actual function. Can you share a Minimum Working Example?

You could have a look at sort!

julia> a = [2,3,1];

julia> sort!(a);

julia> a
3-element Vector{Int64}:
 1
 2
 3

julia> @which sort!(a)
sort!(v::AbstractVector; alg, lt, by, rev, order) in Base.Sort at sort.jl:705

See a related f90 code:
AmplitudeSourceLocation/raybending.F90 at master · mogiso/AmplitudeSourceLocation (github.com)
The inout type indicates arrays with in-place operations, without allocations.

Looking at the code, numerical operations could well dominate allocation times.
The following package can help to answer such questions:
KristofferC/TimerOutputs.jl: Formatted output of timed sections in Julia (github.com)