JPEGli 的编码器能以相同主观质量生成更小的 JPEG 文件 [1],但它的 CPU 解码器比常用替代方案慢。这个项目把 JPEGli 的重建以及一部分经过筛选的基线熵解码移到 Metal,同时保持输出逐字节相同。

CLIC 2025 测试集 [2] 的 30 张 Q90、4:2:0 图像上,基线 JPEG 的逐图中位解码时间之和分别为:单线程 CPU JPEGli 304.8 毫秒、TurboJPEG 149.5 毫秒、Apple ImageIO 183.5 毫秒。渐进式 JPEG 的对应总时间为 629.4、464.1 和 571.5 毫秒。

两幅折线图比较 CPU JPEGli、TurboJPEG 和 Apple ImageIO 在质量等级 25 到 100 下解码基线与渐进式 4:2:0 JPEG 的时间。TurboJPEG 始终最快,CPU JPEGli 通常最慢。
基线与渐进式 4:2:0。每个点是 30 张图像逐图中位解码时间之和。纵轴采用 log₂ 刻度,因此相同比率占用相同高度。曲线是质量等级正序与逆序两轮的中点,色带覆盖两轮范围。

在基线扫描中,TurboJPEG 大约比 CPU JPEGli 快一倍。

这段差距部分来自有意的重建选择。TurboJPEG 常用的 8 位路径通过高度优化的整数 SIMD 完成逆 DCT、色度上采样和颜色转换 [10]。JPEGli 则在拉普拉斯模型下,把每个非零 DCT 系数反量化为其量化区间的期望值,然后一直使用浮点数完成反量化、逆 DCT、上采样和颜色转换,直到最终输出转换 [11]。这样把整数舍入推迟到最后,支持 16 位和浮点输出,并保留 JPEGli 基于期望值重建的精度;代价是 CPU 需要为每个输出像素完成更多工作。

接下来要验证的是:M4 GPU 能否在一次只解码一张图时缩小这段差距。

实现

CPU 始终负责 JPEG 标记和格式状态。渐进式扫描、重启间隔和不支持的输入继续使用现有 CPU 熵解码。对于符合条件的单扫描基线图像,CPU 找到扫描区间、移除字节填充并准备 Huffman 表;Metal 让固定大小的数据块自同步,解码量化系数,用前缀扫描恢复 DC 依赖,再继续完成反量化、8×8 IDCT、色度上采样和 RGBA 转换。

架构图用方框展示 CPU 标记解析和熵计划、运行时选择的 CPU 或 GPU 熵解码、共享系数平面、Metal 重建、直接纹理与扫描行输出,以及精确 CPU 回退。
渐进式和重启扫描状态保留在 CPU。符合条件的基线熵解码与重建交给 Metal;所有不支持的情况都回退到现有精确路径。

后端直接使用 Objective-C++ 和 Metal。它延迟初始化,复用有明确上限的暂存内存,并可释放保留的 GPU 资源。现有扫描行 API 保持不变;另一个 Apple 专用接口可以直接返回 Metal 纹理,避免 CPU 回读。

单图延迟

对于预热后的 Q90、4:2:0 基线图像,直接 Metal 把中位延迟从 9.571 ms 降到 4.476 ms,降低 53.2%;逐图配对中位加速比为 2.058×。p95 从 12.878 ms 降到 7.212 ms。

JPEG 配置 CPU JPEGli p50 Metal 扫描行 p50 直接纹理 p50 直接纹理加速比
基线 4:2:0 9.571 ms 5.158 ms 4.476 ms 2.058×
基线 4:4:4 12.393 ms 7.205 ms 6.381 ms 1.887×
渐进式 4:2:0 18.982 ms 14.779 ms 14.065 ms 1.338×
渐进式 4:4:4 26.963 ms 22.061 ms 21.354 ms 1.255×
两幅折线图比较 CPU JPEGli、TurboJPEG、Apple ImageIO 和直接 Metal JPEGli 在质量等级 25 到 100 下解码基线与渐进式 4:2:0 JPEG 的时间。
30 个基线和渐进式 4:2:0 JPEGli 文件的预热后串行解码。Metal 直接输出 RGBA8 纹理,不回读 CPU。每个点汇总逐图中位数;纵轴为 log₂。

对于基线文件,直接 Metal 在 Q25 到 Q90 之间最快;Q95 和 Q100 则由 TurboJPEG 领先。对于渐进式文件,TurboJPEG 始终最快,而直接 Metal 在每个质量等级都快于 CPU JPEGli 和 ImageIO。

渐进式收益较小,因为熵解码和扫描处理仍在 CPU 上。冷启动时,直接纹理基线解码仍快于 CPU JPEGli:7.928 ms 对 9.639 ms。Metal 初始化耗时 0.28–0.40 ms。

这些都是串行单图结果。基准测试没有重叠图像,也没有使用工作线程。

Metal 在哪些区域同时降低延迟和进程归属能耗

能耗测试包含十张图和六种 JPEG 配置,覆盖基线与渐进式、Q50/Q90/Q95,以及 4:2:0、4:2:2 和 4:4:4。下图展示完整图像尺寸范围内,每百万解码像素的进程归属能耗。

两幅折线图比较 CPU JPEGli、TurboJPEG、Apple ImageIO 和当前运行时选择的 Metal JPEGli 解码器对不同输出尺寸的基线与渐进式 JPEG 进行解码时,每百万像素的进程归属能耗。
每个点是该图像尺寸下逐项中位数的几何平均;色带覆盖实测配置和图像内容范围。Metal 曲线使用当前 AUTO 熵解码策略。越低越好。

对于至少 1 MP 的图像,当前直接 Metal 在全部 24/24 个测试中都同时快于 CPU JPEGli,并减少进程归属能耗。基线延迟降低 63.9%,进程归属能耗降低 82.4%;渐进式延迟降低 26.0%,进程归属能耗降低 33.4%。

相对 TurboJPEG,优势区域是至少 1 MP 的基线图像。当前直接 Metal 快 12.5%,进程归属能耗低 53.2%,16 个测试中有 13 个同时改善两项指标。同一区域的 CPU+GPU 供电轨能耗低 3.9%。大型渐进式文件仍比 TurboJPEG 慢 3.6%,进程归属能耗高 2.3%。低于 1 MP 时,TurboJPEG 仍是更好的选择。

直接输出是这个结果的一部分。加入 CPU 回读后,在大型基线区域中,Metal 比 TurboJPEG 慢 5.5%。图中的能耗来自 macOS 进程归属统计,不是电池或插座测量。

交叉点和运行时策略

JPEGli CPU 与 Metal 的交叉点扫描包含 13 种尺寸,从 4,096 到 12,582,912 像素。下图的纵轴是对数刻度,因此 0.5× 到 1× 与 1× 到 2× 的高度相同。

完整 13 种尺寸扫描展示 p50 和 p95 的 CPU JPEGli 延迟除以 Metal 到 CPU 延迟,并标出 480,000 像素策略边界。
高于 1× 表示 Metal 到 CPU 更快。完整扫描和另一次 12 配置边界测试支持 JPEGli AUTO 使用 480k 像素阈值。

可以使用两条规则:

需要与 JPEGli 完全相同的输出:
    低于 480k 像素       -> CPU JPEGli
    480k 像素及以上       -> Metal JPEGli

在符合条件的基线 Metal 解码内部:
    第一张图或低于 1.5 MP       -> CPU 熵解码
    精细量化 + 合适的熵密度      -> GPU 熵解码
    其他情况                     -> CPU 熵解码

允许输出不同,且下一个消费者在 GPU 上:
    基线,至少 1 MP        -> 直接 Metal JPEGli
    其他情况               -> TurboJPEG

第一条规则在两条逐字节相同的 JPEGli 重建路径之间选择。熵解码选择器更窄:它要求精细的亮度量化表,以及每像素 1.75–5.5 个编码位;直接 4:2:0 的下限为 3.0 位。渐进式、重启和多扫描文件继续使用 CPU 熵解码。最后一条是根据这组 M4 Max 数据拟合的更广泛应用策略。把它应用到 60 个实测能耗组合后,相对始终使用 TurboJPEG,进程归属能耗降低 18.3%,延迟降低 3.5%。在其他 Apple 芯片和图像集上应重新验证。

图像质量不是解码器论据

Bruse 等人 [1] 发现,JPEGli 大约用每像素 1.5 位,就能达到每像素 2.1 位 libjpeg-turbo 图像的估计感知质量,相当于码率降低 28%。这项结果支持 JPEGli 编码器。

我还使用 SSIMULACRA2 [3]、Butteraugli [4]、ColorVideoVDP [5] 和 DISTS [6] 比较了 CPU JPEGli、TurboJPEG 与 ImageIO 对 JPEGli 文件的解码结果。测试覆盖 30 张图、Q25–Q100,以及 4:4:4、4:2:2 和 4:2:0。结果没有找到一致胜出的解码器,也不支持按质量指标选择解码器。

因此,这条后端的理由很直接:应用需要 JPEGli 的重建结果时,Metal 可以在实测区域内用更少延迟和进程归属能耗生成相同像素。这不是“JPEGli 永远是最佳 JPEG 解码器”的主张。

覆盖范围与前人工作

Metal 重建覆盖基线和渐进式 JPEG、灰度、RGB/YCbCr、4:4:4、4:2:2、4:2:0、奇数尺寸和重启间隔。GPU 熵解码范围更窄:没有重启标记的单扫描基线输入。渐进式、重启、增量、畸形和不支持的情况会透明使用 CPU 熵解码。测试还覆盖畸形输入、abort/destroy 清理、禁用 Metal 的构建、安装头文件、导出符号和现有 libjpeg 兼容 API。

Sodsong 等人的 2016 年解码器 [7] 是重建路径最接近的前例:它把熵解码留在 CPU,把 IDCT、上采样和颜色转换移到 OpenCL,并在运行时模型中使用图像尺寸和熵。基线路径更接近 JParEnt [8],但它在 GPU 上建立数据块状态和 DC 前缀,而不是对每张图都使用 GPU 熵解码。Weißenberger 和 Schmidt [9] 为面向吞吐量的目标把更多 JPEG 工作移到 GPU。本项目只在能降低一张消费级图像延迟的区域使用这些思路。

参考文献

  1. Martin Bruse、Luca Versari、Zoltan Szabadka、Jyrki Alakuijala。“Users Prefer Jpegli over Same-sized libjpeg-turbo or MozJPEG.” arXiv:2403.18589,2024。
  2. Challenge on Learned Image Compression。“CLIC 2025 Tasks and Data.” 第 7 届 Challenge on Learned Image Compression,2025。
  3. Jon Sneyers。“SSIMULACRA2: A Perceptual Image Quality Metric.” 项目仓库,2023。
  4. Google。“Butteraugli: A Tool for Measuring Perceived Differences Between Images.” 项目仓库,2023。
  5. Rafał K. Mantiuk、Param Hanji、Maliha Ashraf、Yuta Asano、Alexandre Chapiro。“ColorVideoVDP: A Visual Difference Predictor for Image, Video, and Display Distortions.” ACM Transactions on Graphics 43(4),文章 129,2024。
  6. Keyan Ding、Kede Ma、Shiqi Wang、Eero P. Simoncelli。“Image Quality Assessment: Unifying Structure and Texture Similarity.” IEEE Transactions on Pattern Analysis and Machine Intelligence 44(5),2567–2581,2022。
  7. Wasuwee Sodsong、Jingun Hong、Seongwook Chung、Yeong-Kyu Lim、Shin-Dug Kim、Bernd Burgstaller。“Dynamic Partitioning-based JPEG Decompression on Heterogeneous Multicore Architectures.” Concurrency and Computation: Practice and Experience 28(2),517–536,2016。DOI:10.1002/cpe.3620。
  8. Wasuwee Sodsong、Minyoung Jung、Jinwoo Park、Bernd Burgstaller。“JParEnt: Parallel Entropy Decoding for JPEG Decompression on Heterogeneous Multicore Architectures.” Concurrency and Computation: Practice and Experience 29,e4111,2017。
  9. André Weißenberger、Bertil Schmidt。“Accelerating JPEG Decompression on GPUs.” 2021 IEEE 28th International Conference on High Performance Computing, Data, and Analytics (HiPC),121–130,2021。DOI:10.1109/HiPC53243.2021.00026。
  10. libjpeg-turbo Project。“SIMD Coverage of the libjpeg Algorithms.” 项目文档,2026。
  11. Google。“Jpegli: an improved JPEG encoder and decoder implementation.” 项目仓库,2026。 Metal 解码器源码和基准测试延迟结果四指标质量语料能耗报告都在实验分支上。