Repository navigation
Jpeg encoding code optimization - #1632
JimBobSquarePants merged 106 commits into
Conversation
saucecontrol
left a comment
There was a problem hiding this comment.
Really nice improvements! Left a comment on the SIMD 2:1 box filter if you want to push it a bit further
|
@saucecontrol did a little research about 8x4 -> 4x2 downscaling based on your ideas.
Note that this benchmark uses current
And it runs almost 50% faster:
The only thing that bothers me is quad word permutation: ...
Vector256<float> avg2x2 = ...; // average for 4 values
...
var per = Avx2.Permute4x64(Unsafe.As<Vector256<float>, Vector256<double>>(ref avg2x2), 0b11_01_10_00);
return Unsafe.As<Vector256<double>, Vector256<float>>(ref per);I guess without manual IL code injection (which is not that easy by itself) it's impossible to write it better? |
|
That's great! I had the same thought about the horizontal adds late last night but was too lazy to go back upstairs to my computer 😆 Horizontal add is implemented in microcode in the processor, and it's effectively broken down into a shift (with an order that doesn't map to an instruction exposed publicly), an add, and an unpack. So it's actually only one cycle faster than the current code that does 3 shifts and an add. But yeah, doing the vertical portion first really cleans it up. And hopefully the smaller code makes it possible to get rid of the code in the outer method that spills those to the stack. (I didn't spend enough time looking at that to figure out what it's doing entirely). Oh, and you don't need |
|
Yep, code is much cleaner and smaller with your additions. Didn't know about no-op for those casts. Thank you for your contribution to this pr, getting smarter everyday! 😄 |
|
@JimBobSquarePants waiting for new commits to be built & checked and we are ready to merge I guess! |
|
@br3aker Looks like you've got a https://github.com/SixLabors/ImageSharp/pull/1632/checks?check_run_id=2789197791#step:10:256 Edit. |
|
@JimBobSquarePants my bad, did check for |
JimBobSquarePants
left a comment
There was a problem hiding this comment.
I can't see any issues here. @br3aker really, really great work!!
I'll leave it one more day so others can have a final look though before merging though s this is tricky stuff and I might have missed something.
|
@JimBobSquarePants fixed disposable thingy in benchmarks & updated them:
Already beating |
|
Waaaat, first time ever seeing |
|
Looks like the ImageMagick reference decoder is also very greedy on memory, don't mind it, nothing to do with your code. |
|
Lets get this merged!! 🎉 |
Prerequisites
Description
This is a draft due to 4 and some small internal jpeg changes I will adress in a separate comment. Want to hear your thoughts on this.
Jpeg format encoding optimization & code cleanup.
HuffmanScanEncoderfollowing logic ofHuffmanScanDecoderin jpeg decoding code (did todo comment from Encode444/Encode420, basically).1024, Looks like it's optimal for general use case, lesser size would lead to worse performance, bigger size doesn't bring any performance boost at all (on my machine atleast). Right now it is defined by constant atHuffmanScanEncoderclass, it can be injected from the callee/global config but I'm not sure it is really needed.Block8x8F. Most, if not all, avx-intrinsic code use a lot ofUnsafe.Ascasts like here:With new layout it can be simplified to:
There's also a performance gain but it's too small to really affect any heavy algorithms like jpeg decoding/encoding.
Note: This PR does not change any existing code with
Unsafe.Ascalls. If it gets merged - this can be a separatecodequalityissue (good-first-issue maybe?)Stats
Benchmarks are based on this noise image with different sizes:

Also tested some random images from beeheads demo but they are too large for gaining stable results in a reasonable amount of time :P
Even so, got ~100-200ms performance gain on those.
Jpeg encoding to
MemoryStream(disk writes are less stable):Avx accelerated cosine transforms: