Requesting Help with Optimizing Code
Kyle Ingraham
kyle at kyleingraham.com
Thu Apr 8 01:24:23 UTC 2021
Hello all. I have been working on learning computational
photography and have been using D to do that. I recently got some
code running that performs [chromatic
adaptation](https://en.wikipedia.org/wiki/Chromatic_adaptation)
(white balancing). The output is still not ideal (image is
overexposed) but it does correct color casts. The issue I have is
with performance. With a few optimizations found with profiling I
have been able to drop processing time from ~10.8 to ~6.2 seconds
for a 16 megapixel test image. That still feels like too long
however. Image editing programs are usually much faster.
The optimizations that I've implemented:
* Remove `immutable` from constants. The type mismatch between
constants (`immutable(double)`) and pixel values (`double`)
caused time-consuming checks for compatible types in mir
operations and triggered run-time type conversions and memory
allocations (sorry if I butchered this description).
* Use `mir.math.common.pow` in place of `std.math.pow`.
* Use `@optmath` for linearization functions
(https://github.com/kyleingraham/photog/blob/up-chromadapt-perf/source/photog/color.d#L192 and https://github.com/kyleingraham/photog/blob/up-chromadapt-perf/source/photog/color.d#L318).
Is there anything else I can do to improve performance?
I tested the code under the following conditions:
* Compiled with `dub build --build=release --compiler=ldmd2`
* dub v1.23.0, ldc v1.24.0
* Intel Xeon W-2170B 2.5GHz (4.3GHz turbo)
* [Test
image](https://user-images.githubusercontent.com/25495787/113943277-52054180-97d0-11eb-82be-934cf3d22112.jpg)
* Test code:
```d
#!/usr/bin/env dub
/+ dub.sdl:
name "photog-test"
dependency "photog" version="~>0.1.1-alpha"
dependency "jpeg-turbod" version="~>0.2.0"
+/
import std.datetime.stopwatch : AutoStart, StopWatch;
import std.file : read, write;
import std.stdio : writeln, writefln;
import jpeg_turbod;
import mir.ndslice : reshape, sliced;
import photog.color : chromAdapt, Illuminant, rgb2Xyz;
import photog.utils : imageMean, toFloating, toUnsigned;
void main()
{
const auto jpegFile = "image-in.jpg";
auto jpegInput = cast(ubyte[]) jpegFile.read;
auto dc = new Decompressor();
ubyte[] pixels;
int width, height;
bool decompressed = dc.decompress(jpegInput, pixels, width,
height);
if (!decompressed)
{
dc.errorInfo.writeln;
return;
}
auto image = pixels.sliced(height, width, 3).toFloating;
int err;
double[] srcIlluminant = image
.imageMean
.reshape([1, 1, 3], err)
.rgb2Xyz
.field;
assert(err == 0);
auto sw = StopWatch(AutoStart.no);
sw.start;
auto ca = chromAdapt(image, srcIlluminant,
Illuminant.d65).toUnsigned;
sw.stop;
auto timeTaken = sw.peek.split!("seconds", "msecs");
writefln("%d.%d seconds", timeTaken.seconds, timeTaken.msecs);
auto c = new Compressor();
ubyte[] jpegOutput;
bool compressed = c.compress(ca.field, jpegOutput, width,
height, 90);
if (!compressed)
{
c.errorInfo.writeln;
return;
}
"image-out.jpg".write(jpegOutput);
}
```
Functions found through profiling to be taking most time:
* Chromatic adaptation:
https://github.com/kyleingraham/photog/blob/up-chromadapt-perf/source/photog/color.d#L354
* RGB to XYZ:
https://github.com/kyleingraham/photog/blob/up-chromadapt-perf/source/photog/color.d#L142
* XYZ to RGB:
https://github.com/kyleingraham/photog/blob/up-chromadapt-perf/source/photog/color.d#L268
A profile for the test code is
[here](https://github.com/kyleingraham/photog/files/6274974/trace.zip). The trace.log.dot file can be viewed with xdot. The PDF version is [here](https://github.com/kyleingraham/photog/files/6275358/trace.log.pdf). The profile was generated using:
* Compiled with dub build --build=profile --compiler=ldmd2
* Visualized with profdump - dub run profdump -- -f -d -t 0.1
trace.log trace.log.dot
The branch containing the optimized code is here:
https://github.com/kyleingraham/photog/tree/up-chromadapt-perf
The corresponding release is here:
https://github.com/kyleingraham/photog/releases/tag/v0.1.1-alpha
If you've gotten this far thank you so much for reading. I hope
there's enough information here to ease thinking about
optimizations.
More information about the Digitalmars-d
mailing list