JuliaImages / JuliaImages/ImageFiltering.jl

imfilter! is slower with an Array source than an OffsetArray

Open
#95 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Julia
Stars
104
Forks
52
PR merge metrics
No merged PRs in 30d

Description

Could imfilter use the secret sauce from the specialization for OffsetArray in more cases? I've not wrapped my head fully around all the indexing permutations, but here's a simple benchmark test case:

This hits the fast OffsetArray implementation:

img = rand(0:1, 1024, 1024)
const kern = ImageFiltering.factorkernel(centered([10 2 10; 2 1 2; 10 2 10]))
src = ImageFiltering.padarray(Int, img, Pad(:reflect, 1,1))
dest = similar(img)
@benchmark imfilter!($dest, $src, kern, ImageFiltering.NoPad())
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     11.882 ms (0.00% GC)
  median time:      11.904 ms (0.00% GC)
  mean time:        11.910 ms (0.00% GC)
  maximum time:     13.976 ms (0.00% GC)
  --------------
  samples:          420
  evals/sample:     1

Theoretically, I think this could be faster as it does fewer computations than the one above (it skips the outside edge, yes?), but it falls back to the generic implementation:

src = img
dest = OffsetArray(similar(img, size(img).-2), (1, 1))
@benchmark imfilter!($dest, $src, kern, ImageFiltering.NoPad())
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     19.408 ms (0.00% GC)
  median time:      19.470 ms (0.00% GC)
  mean time:        19.501 ms (0.00% GC)
  maximum time:     21.914 ms (0.00% GC)
  --------------
  samples:          257
  evals/sample:     1

This restores a bit of performance and hits the specialized method, but it's still a bit slower:

src = OffsetArray(img, (0,0))
dest = OffsetArray(similar(img, size(img).-2), (1, 1))
@benchmark imfilter!($dest, $src, kern, ImageFiltering.NoPad())
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     13.947 ms (0.00% GC)
  median time:      13.965 ms (0.00% GC)
  mean time:        13.985 ms (0.00% GC)
  maximum time:     18.823 ms (0.00% GC)
  --------------
  samples:          358
  evals/sample:     1

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read the specialized and generic implementations in src/imfilter.jl around lines 997 and 1012. Reproduce the three Julia benchmark cases from the issue, then trace the indexing permutations that determine method selection. Done means the Array-source case uses an appropriate fast path without changing imfilter! results, with the benchmark showing the expected improvement.

Written by the indexing model from the issue text.

Assessment

Tech stack
julia
Domain
computer-vision, performance
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.