# 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?

``````"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)