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

Performance in Julia 0.5 #30

Closed
Cody-G opened this issue Mar 7, 2017 · 13 comments
Closed

Performance in Julia 0.5 #30

Cody-G opened this issue Mar 7, 2017 · 13 comments

Comments

@Cody-G
Copy link

Cody-G commented Mar 7, 2017

I'm getting slow performance with RegisterWorkerApertures.PreprocessSNF in Julia 0.5. It now takes a couple of minutes to filter an image when it used to take a couple of seconds. I'm still not great at reading the output of code_warntype but I think the Any types at the end may reflect a type inference problem? I'm profiling it now, will post the result.

 julia> @code_warntype RegisterWorkerApertures.PreprocessSNF(100, sigmalp, sigmahp)(fixed0_cropped)
Variables:
  pp::RegisterDriver.PreprocessSNF
  A::ImageMetadata.ImageMeta{Float32,3,AxisArrays.AxisArray{Float32,3,SubArray{Float32,3,Array{Float32,3},Tuple{UnitRange{Int64},UnitRange{Int64},UnitRange{Int64}},false},Tuple{AxisArrays.Axis{:x,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}},AxisArrays.Axis{:l,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}},AxisArrays.Axis{:z,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}}}}}
  Af::Array{Float32,3}
  #temp#::LambdaInfo

Body:
  begin 
      SSAValue(0) = (Core.getfield)(A::ImageMetadata.ImageMeta{Float32,3,AxisArrays.AxisArray{Float32,3,SubArray{Float32,3,Array{Float32,3},Tuple{UnitRange{Int64},UnitRange{Int64},UnitRange{Int64}},false},Tuple{AxisArrays.Axis{:x,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}},AxisArrays.Axis{:l,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}},AxisArrays.Axis{:z,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}}}}},:data)::AxisArrays.AxisArray{Float32,3,SubArray{Float32,3,Array{Float32,3},Tuple{UnitRange{Int64},UnitRange{Int64},UnitRange{Int64}},false},Tuple{AxisArrays.Axis{:x,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}},AxisArrays.Axis{:l,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}},AxisArrays.Axis{:z,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}}}}
      # meta: location /home/cody/.julia/v0.5/BlockRegistrationScheduler/src/RegisterDriver.jl PreprocessSNF 224
      # meta: location /home/cody/.julia/v0.5/BlockRegistrationScheduler/src/RegisterDriver.jl preprocess 221
      Af::Array{Float32,3} = $(Expr(:invoke, LambdaInfo for sqrt_subtract_bias(::AxisArrays.AxisArray{Float32,3,SubArray{Float32,3,Array{Float32,3},Tuple{UnitRange{Int64},UnitRange{Int64},UnitRange{Int64}},false},Tuple{AxisArrays.Axis{:x,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}},AxisArrays.Axis{:l,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}},AxisArrays.Axis{:z,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}}}}, ::Float32), :(RegisterDriver.sqrt_subtract_bias), SSAValue(0), :((Core.getfield)(pp,:bias)::Float32))) # line 222:
      SSAValue(2) = (Core.getfield)(pp::RegisterDriver.PreprocessSNF,:sigmahp)::Array{Float32,1}
      SSAValue(3) = $(Expr(:invoke, LambdaInfo for highpass(::Type{Float32}, ::Array{Float32,3}, ::Array{Float32,1}), :(RegisterCore.highpass), Float32, :(Af), SSAValue(2)))
      SSAValue(1) = (Core._apply)(Core.tuple,(Core.getfield)(pp::RegisterDriver.PreprocessSNF,:sigmalp)::Array{Float32,1})::Tuple{Vararg{Float32,N}}
      # meta: pop location
      # meta: pop location
      return (RegisterDriver.shareproperties)(A::ImageMetadata.ImageMeta{Float32,3,AxisArrays.AxisArray{Float32,3,SubArray{Float32,3,Array{Float32,3},Tuple{UnitRange{Int64},UnitRange{Int64},UnitRange{Int64}},false},Tuple{AxisArrays.Axis{:x,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}},AxisArrays.Axis{:l,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}},AxisArrays.Axis{:z,Ranges.LinSpace{Quantity{Float64, Dimensions:{𝐋}, Units:{μm}}}}}}},(RegisterDriver.imfilter)(SSAValue(3),(ImageFiltering.KernelFactors.#IIRGaussian)($(Expr(:invoke, LambdaInfo for vector_any(::Any, ::Vararg{Any,N}), :(Base.vector_any), :(:emit_warning), true)),ImageFiltering.KernelFactors.IIRGaussian,(Core._apply)(ImageFiltering.KernelFactors.promote_type,(ImageFiltering.KernelFactors.map)(ImageFiltering.KernelFactors.iirgt,SSAValue(1))::Any)::Type{T},SSAValue(1))::Union{Tuple{ImageFiltering.KernelFactors.ReshapedOneD{T,N,Npre,_<:ImageFiltering.KernelFactors.TriggsSdika},ImageFiltering.KernelFactors.ReshapedOneD{T,N,Npre,_<:ImageFiltering.KernelFactors.TriggsSdika},Vararg{Any,N}},Tuple{ImageFiltering.KernelFactors.ReshapedOneD{T,N,Npre,_<:ImageFiltering.KernelFactors.TriggsSdika}}})::Any)::AbstractArray{T,N}
  end::AbstractArray{T,N}
@Cody-G
Copy link
Author

Cody-G commented Mar 7, 2017

Looks like all of the time is spent on the imfilter function, with most of that time going to indexing with OffsetArrays

@timholy
Copy link
Member

timholy commented Mar 7, 2017

Oh dear. Do you have a simple repro? When I try this:

julia> using Unitful, AxisArrays, ImageFiltering

julia> const μm = u"μm"

julia> A = rand(Float32, 1000, 1000, 60);

julia> AA = AxisArray(A, (:x, :l, :z), (0.771μm, 0.771μm, 5μm));

julia> imfilter(A, Kernel.gaussian((3,3,1)));

I see it uses an FFT-based algorithm. So I don't think I'm looking at the same thing as you.

@timholy
Copy link
Member

timholy commented Mar 7, 2017

OK, this seems to do it:

julia> using Images, BlockRegistrationScheduler

julia> ps = pixelspacing(AA)
(0.771 μm,0.771 μm,5 μm)

julia> sigmahp = Float64[25μm/x for x in ps]

julia> pp = PreprocessSNF(0.01, zeros(3), sigmahp)
RegisterDriver.PreprocessSNF(0.01f0,Float32[0.0,0.0,0.0],Float32[32.4254,32.4254,5.0])

julia> pp(AA)

I'll investigate.

Also, is 100 the proper setting for the bias anymore? Remember that the output of load("myfile.imagine") went from UInt16 to N0f16, which means it was scaled by 1/65535.

@timholy
Copy link
Member

timholy commented Mar 7, 2017

Try this diff (adds an @inline in front of line 128):

$ git diff
diff --git a/src/OffsetArrays.jl b/src/OffsetArrays.jl
index 10e5f0c..2d85db2 100644
--- a/src/OffsetArrays.jl
+++ b/src/OffsetArrays.jl
@@ -125,7 +125,7 @@ Base.fill(x, inds::Tuple{UnitRange,Vararg{UnitRange}}) =
 ### Low-level utilities ###
 
 # Computing a shifted index (subtracting the offset)
-offset{N}(offsets::NTuple{N,Int}, inds::NTuple{N,Int}) = _offset((), offsets, inds)
+@inline offset{N}(offsets::NTuple{N,Int}, inds::NTuple{N,Int}) = _offset((), offsets, inds)
 _offset(out, ::Tuple{}, ::Tuple{}) = out
 @inline _offset(out, offsets, inds) =
     _offset((out..., inds[1]-offsets[1]), Base.tail(offsets), Base.tail(inds))

@timholy
Copy link
Member

timholy commented Mar 7, 2017

Also, if you're desperate for more performance, try annotating the bounds-checks in OffsetArrays with @checkbounds. Those are deliberately not there for now for reasons described in the devdocs, but you could put them in locally.

@timholy
Copy link
Member

timholy commented Mar 11, 2017

Did this fix your performance problem?

@Cody-G
Copy link
Author

Cody-G commented Mar 11, 2017

I got by without filtering for now, and I'm working on segmentation for my upcoming department talk. Hoping I can return to this soon.

@timholy
Copy link
Member

timholy commented Mar 11, 2017

Gotcha. If you don't need filtering, better not to do it anyway.

@Cody-G
Copy link
Author

Cody-G commented Mar 14, 2017

OK that definitely solved the problem! imfilter is about 100 times faster now!

@timholy
Copy link
Member

timholy commented Mar 14, 2017

Awesome! I'll make the fix in OffsetArrays.

@mdhe1248
Copy link
Contributor

Should the change be merged?
I also had same performance issue. The change fixed the performance issue.

@timholy
Copy link
Member

timholy commented Apr 14, 2017

It's merged in JuliaArrays/OffsetArrays.jl#26, but a new release hasn't been tagged yet.

@timholy
Copy link
Member

timholy commented Apr 15, 2017

New release has been merged into METADATA.

@timholy timholy closed this as completed Apr 15, 2017
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

3 participants