Reduce indexing overhead in symmetric resize filters - #3097
Conversation
197g
left a comment
There was a problem hiding this comment.
Odd that this would be faster, I'd assumed they indices are perfect for LLVM to reason about the lengths and the elide a lot by itself. Though overflow may make it far less obvious ht pattern in filter_1d is very counterintuitive. Since the largest index happens last, there are surely four different panic paths here?
Can you look into more alternatives here that optimize? It still seems rather odd. For instance, maybe this pattern could work:
let bw = src[other_side * N..].first_chunk::<4>().unwrap();
// Destructuring may not be necessary.
let [bw0, bw1, bw2, bw3] = bw;
It isn't faster. At least on my machine.
|
|
Also, are we going to enforce our LLM policy? The PRs by them are obviously in violation, and I don't think there's a clearer example of an agent just spamming PRs. Aside: funny and relevant. I saw their blog post after writing this comment and had to chuckle. |
|
I think the only reasonable thing that can be done here without SIMD is to wait until we want to enable min version 1.94 and use https://doc.rust-lang.org/std/slice/struct.ArrayWindows.html. Since our previous discussion, I discovered that Regarding the LLM-generated PR, starting from some LLVM version (or Rust version), it became smart enough to sometimes determine that read operations which do not mutate anything ( or borrow checker can prove that mutation isn't overlapping ) can be reshuffled, so if the |
Given that the closing paragraph seems to be fabulation rather than human input, yes. |

Summary
This reduces overhead in the symmetric resize filter inner loops by indexing the working buffers directly instead of creating short temporary slices for each pixel lane.
The arithmetic and source positions are unchanged. The patch only removes repeated one-element and four-element slice construction in
filter_symmetric_columnandfilter_symmetric_row.Why
filter_symmetric_rowandfilter_symmetric_columnare used by the non-nearest resize filters. These loops run once per output pixel, so avoiding extra slice construction and repeated range expressions keeps the hot path a little smaller while preserving the same bounds-checked indexing pattern.Validation
cargo fmt --all --checkgit diff --checkcargo test -p image --lib imageopscargo bench --bench imageops -- resize --baseline upstream-mainBenchmark
I ran the repository
imageopsresize benchmark on the same machine, first saving anupstream-mainbaseline from the currentmainbranch and then comparing this branch against it.resize 400x300 Gaussianresize 400x300 Lanczos3large/resize 2000x2000 Trianglelarge/resize 2000x2000 CatmullRomlarge/resize 2000x2000 Gaussian