perf: optimize horizontal and float predictor decode
Horizontal predictor (one_byte_predict, all integer TIFFs with Predictor=2): rewrite with explicit [u8; N] accumulator so LLVM unrolls and keeps each channel in a register. For N=3 (RGB8), this replaces a scalar 1-byte-per-iteration loop with a 2x-unrolled 3-register loop. Float predictor (Predictor=3, f16/f32/f64): split deinterleave into per-format functions with plane slicing up front; f32 batches 4 samples through a u128 wide store to eliminate per-sample bounds checks. Thread a reusable scratch buffer through expand_chunk to eliminate per-row heap allocation. Benchmarked on real 21MP photos and GeoTIFF DEMs (vs upstream main): Strip RGB8 deflate+hpred: 253ms -> 224ms (-11%) Strip RGB8 LZW: 405ms -> 370ms (-9%) Tiled RGB8 deflate+hpred: 241ms -> 222ms (-8%) Strip RGB f32 deflate+fpred: 726ms -> 527ms (-27%) Gray f32 tiled 512: 290ms -> 166ms (-43%) Copernicus DEM GeoTIFF: 239ms -> 152ms (-37%) USGS DEM GeoTIFF: 284ms -> 198ms (-30%)
This commit is contained in:
1 parent
dc94cd4436
commit
fa8a911f79
2 files changed
+197
-58
No files matched your search
@@ -1009,6 +1009,7 @@ impl Image {
|
||||
buf: &mut [u8],
|
||||
layout: &ReadoutLayout,
|
||||
chunk_index: u32,
|
||||
scratch: &mut Vec<u8>,
|
||||
) -> TiffResult<()> {
|
||||
let ValueReader {
|
||||
reader,
|
||||
@@ -1191,6 +1192,7 @@ impl Image {
|
||||
samples,
|
||||
ByteOrder::native(),
|
||||
predictor,
|
||||
scratch,
|
||||
);
|
||||
|
||||
if photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
||||
@@ -1209,6 +1211,7 @@ impl Image {
|
||||
samples,
|
||||
decompressed_byte_order,
|
||||
predictor,
|
||||
scratch,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1255,6 +1258,7 @@ impl Image {
|
||||
samples,
|
||||
decompressed_byte_order,
|
||||
predictor,
|
||||
scratch,
|
||||
);
|
||||
|
||||
if photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
||||
@@ -1296,6 +1300,7 @@ impl Image {
|
||||
samples,
|
||||
decompressed_byte_order,
|
||||
predictor,
|
||||
scratch,
|
||||
);
|
||||
|
||||
if photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
||||
|
||||
Reference in new issue
Block a user