HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

veImageX 演进之路:FPGA HEIF 静图编码服务性能优化

  • 2022-12-14
    北京
  • 本文字数:3030 字

    阅读完需:约 10 分钟

veImageX演进之路:FPGA HEIF 静图编码服务性能优化

前言


压缩技术对于图像、视频应用十分重要。在保证同样主观质量的前提下,如何将图像压缩到更小体积便于互联网信息传输,火山引擎视频云团队不断突破压缩技术“天花板”。


字节跳动在公司成立之初就建设了图像处理平台,起初主要服务于今日头条 APP 的图文资源。随着业务扩展,后逐步服务于抖音图集、短视频封面、图虫等几乎用户能看到的所有图片展示场景。火山引擎视频云团队将字节跳动图像处理的实践,整理为《veImageX演进之路》系列,将从产品应用、后端技术、前端技术、算法、客户端 SDK 详细解读字节跳动背后的图像技术。


veImageX 是火山引擎基于字节跳动内部服务实践,推出的图像一站式解决方案 ,覆盖上传、存储、处理、分发、展示、质量监控全链路应用。

背景


互联网内容的展示离不开图片,通过 CDN 展示分发图片可以提升图片访问速度,但是也需要为带宽付费。HEIF 图片格式有着卓越的压缩性能,相比 WebP 可以节省 30% 的图片码率,由此可以为业务节省相当规模的带宽成本。


但 HEIF 格式是一把双刃剑,相比其他格式,在提升压缩率的同时,也需要消耗更多 CPU 计算资源。为了降低 HEIF 格式的编码计算成本,veImageX 采用了 FPGA 异构架构,逐步将 HEIF 编码的流量从 CPU 计算集群迁移到 FPGA 计算集群。


在流量迁移过程中,最初整体流量较小,FPGA 编码服务看起来很稳定。但随着迁移过程递进,当 FPGA 的单卡 QPS 上涨到一定阈值后,FPGA 卡所在宿主机的性能瓶颈逐渐暴露出来,影响了整体的迁移工作。


本文会对迁移过程中遇到的性能瓶颈做分析,并给出优化解决方案。经过这一系列优化措施,veImageX 整体 CPU 负载从 80% 降低为 30%,相应的服务延时从 140ms 降低为 4ms。

架构

首先,我们看一下 FPGA HEIF 静图分发链路的整体架构。



链路分为三块:

● 业务 App:一般会集成 veImageX 的图片 SDK。既可以兼容各类图片格式(自然也包括 HEIF),提供了图片的下载、解码、展示功能。也支持将访问图片过程中产生的指标数据上报,这样可以方便在控制台查看这些性能指标,比如解码耗时、图片加载成功率等。

● veImageX 分发基础链路:主要解决了图片分发问题,提供了基础的图片实时处理能力。其中 CDN 缓存了图片请求,提供了加速访问的能力;veImageX 源站服务主要负责访问权限的校验、流量控制、图片资源下载以及静态图片的主体处理流程。对于 HEIF 静图编码场景,veImageX 源站服务则需要和 FPGA HEIF 编码服务互动,协作完成。

● FPGA HEIF 编码服务:自上而下可以分为编码服务层、编码驱动层、编码硬件层。


为了解决计算资源异构引入的耦合问题,FPGA HEIF 的编码能力通过 HTTP 服务化的方式提供出来。所有的 FPGA 卡部署于字节跳动自研的 Lambda 计算平台。通过 Lambda 函数+资源虚拟化的方式,将 HEIF 编码功能抽象为上游可直接调用的服务,并能确保将编码请求均衡地调度到各个 FPGA 卡上。物理机上的每一张 FPGA 卡和对应的主机 CPU 和内存资源都被打包,经由 Executor 管理。此外,为了防止 FPGA 卡被突发流量打挂,Executor 内置了一个执行队列,用于控制 FPGA 卡的并发吞吐。


编码服务层主要负责解析 HTTP 请求,获取待编码的图片数据。待编码的图片数据一般通过 JPEG 格式传入,因此其中内嵌了一个 JPEG 解码器。此外,veImageX HEIF 支持自适应编码选项,通过服务层内的自适应模型预测编码所用到的质量参数。服务层中的 HEIF 编码器是一个适配层,屏蔽了底层计算架构的差异,对于 CPU 和 FPGA 都可以提供相同的编码接口,将传入的 RGBA 像素矩阵编码为 HEIF 码流。


编码驱动层中的 FBVC1 编码器可以将图片像素序列编码为二进制码流,上层的 HEIF 编码器拿到这个码流后,按照 HEIF 标准格式封装即可。FBVC1 编码过程中,依赖了 FPGA 驱动库和编码硬件层打交道,发送指令,读写 FPGA 设备。

优化方向

降低线程数

在迁移测试 FPGA 编码服务过程中,我们也遇到了一些性能瓶颈的问题。首当其冲的是,当单机 QPS 达到 2K 时,CPU 负载高达到 60%。通过分析热点,我们可以看到问题出现在 onnxruntime 这个库上。


从调用的 API 很容易联想到,这是一个线程相关问题。我们都知道,如果没有手动设置线程数的话,默认会使用物理机核数作为线程数,导致整体的调度开销比较严重。

因此,需要根据宿主机的 CPU 配置情况,手动配置线程数,不要使用默认配置,最终将 CPU 负载从 57% 降低到 7%。

调优 GOMAXPROCS

HEIF 的编码服务层是使用 Golang 实现的。而 Golang 中使用了 GOMAXPROCS 这个环境编码来控制底层并发度。默认情况下,GOMAXPROCS 是和物理机核数相关。所以这里也遇到了和上一个问题相同的根因,需要限制整体的并发度。

针对 GOMAXPROCS 做了调优,在单机 QPS 达到 8K 时,CPU 负载下降了 6% 。

限制磁盘 IO

首先通过 statio 查看磁盘情况,


再结合下面的火焰图(黑框内有明显的磁盘 IO 操作)


这里很容易能想到这些磁盘 IO 操作导致了整体延迟的升高。但从结果来看,平均 8ms 还在预期范围内。但 HEIF 编码服务对处理的延迟要求较严格,请求处理过慢会导致请求堆积,此时 FPGA 的计算潜力无法做到完全释放。

针对这块定向优化,相关延时下降至 0.5ms,CPU 负载下降 3%。

另外,我们观察到磁盘和 cached memory 较高,这显然不太正常。



进一步定位后,确定是编码服务造成的。详细排查后发现,编码驱动层中的 FPGA 驱动程序的部分调试日志未关闭,导致大量的日志写磁盘。当关闭驱动的调试日志后,CPU 负载下降 5% 。

合并 CGO 调用

编码服务包括两部分的 CGO 调用:

● 自适应编码模型预测:每个请求会有最多 5 次的推理,合并为 Batch,减少为 1 次调用

● FPGA 编码:直接调用 SDK 需要 6 次 CGO 调用,对这部分实现 C 的封装,减少为 2 次调用

这部分优化影响较小,在延迟数据层面不是很明显,模型预测部分可能有几百 us 的优化。

减少 GC

编码服务每次处理请求都需要获取图像 raw data,因此服务会多次创建 []byte 的图像数据对象,容易导致频繁 GC。

一个解决问题的思路是在服务启动前预分配一个固定的对象池,每次请求需要的 []byte 对象直接从对象池里拿。此外,也曾尝试过使用 Golang 标准库中的 sync.Pool,但效果不好,可能的原因是 sync.Pool 里依然有一些 GC 相关的策略,不符合我们这个场景。

这部分优化后,CPU 负载下降了 6% 。

均衡中断

从系统的监控中,我们观察到各 CPU 负载不是很均匀。



编码过程中发生的中断情况


我们可以得出结论,FPGA 的相关中断被只绑定到了特定的 CPU 上,没有分布均匀。这个在当时并没有成为瓶颈,所以优化后没有明显提升。

加速图片解码

我们从火焰图可以看到解码时间占服务延时的较大部分。


对火焰图中黑框内调用栈分析后,观察到有相当部分时间消耗在了 JPEG 解码上。调查后,发现底层 SDK 解码使用了 libjpeg,整体性能不佳。这里我们替换为使用 SIMD 实现的 libjpeg-turbo 解码库后,CPU 负载降低了 10%,耗时减少 2ms。

优化总结

基于优化后的版本再次做性能压测,使用 300x400 分辨率的测试图片,当单机 QPS 达到 10K 时,编码服务整体性能指标变化如下:

●  CPU 负载从 80% 降低为 30%

● 服务延时从 140ms 降低为 4ms

可以看到,经过我们一套“组合拳”优化后,整体编码服务的性能有了明显提升。

写在最后

目前火山引擎 veImageX 已经上述实践形成端到端的解决方案对外输出,帮助每一个互联网企业用更低的成本达到更好的图片加载效果。除了商务降本之外,也可以用更“绿色”的算法降本,为行业降本增效提供了一种创新可能性。


了解更多 veImageX,点击阅读原文:https://www.volcengine.com/products/imagex

2022-12-14 21:142921

评论

发布
暂无评论
发现更多内容

NFT链游系统开发|DeFi+NFT技术搭建

薇電13242772558

NFT 链游

玩转云原生流量管理——Flomesh

Flomesh

云原生 流量控制 #开源

去中心化NFT交易平台开发

开发微hkkf5566

一年一度 OceanBase 技术征文大赛全面开启! 入门实战,等您来写

OceanBase 数据库

数据库

基于任务调度的企业级分布式批处理方案

阿里巴巴云原生

阿里云 分布式 云原生 SchedulerX

Substrate技术及生态5月大事记 | Square One计划启动,波卡上线XCM!

One Block Community

区块链 技术 波卡生态

BI 如何让SaaS产品具有 “安全感”和“敏锐感”(上)

葡萄城技术团队

SaaS BI 数据可视化

集成底座流程测试总结

agileai

测试流程 集成底座 企业服务总线 主数据平台 统一身份管理平台

一对一直播源码部署,是系统上线运行的开始

开源直播系统源码

软件开发 一对一直播 一对一直播源码 直播系统源码

国内首个:ICPR2022多模态字幕识别比赛日前结束

科技热闻

什么是算子下盘

华为云开发者联盟

数据库 集群 算子

印尼Widya Robotics携手华为云,让建筑工地安全看得见

华为云开发者联盟

人工智能 安全 华为云 modelarts 机器视觉

C++ Workflow异步调度框架 - 基本介绍篇

1412

c++ 开源 workflow 异步调度 网络框架

去中心化DEFI质押流动性挖矿项目开发案例(逻辑分析)

开发微hkkf5566

InfoQ 极客传媒 15 周年庆征文|实战 MySQL 高可用架构

悟空聊架构

架构 运维 悟空聊架构 热门活动 InfoQ极客传媒15周年庆

InfoQ 极客传媒 15 周年庆征文|PassJava网站生产级事故复盘

悟空聊架构

运维 前端 passjava 悟空聊架构 InfoQ极客传媒15周年庆

C++ Workflow异步调度框架 - 架构设计篇

1412

c++ 开源 workflow 异步调度 网络框架

Linux系统环境搭建

开发微hkkf5566

大量模块壳工程本地如何快速编译?优酷 iOS 工程插件化实践

阿里巴巴终端技术

ios App 编译 架构设计

【Spring 学习笔记(七)】Spring 管理第三方Bean之管理Druid数据源

倔强的牛角

Java spring Java EE 6月月更

聚焦行业,赋能客户 | 博云容器云产品族五大行业解决方案发布

BoCloud博云

云原生 容器云

物联网低代码平台权限管理,保障平台安全!

AIRIOT

物联网 低代码开发 低代码开发平台 快速开发平台

【高阶知识】用户态协议栈之Epoll实现原理

C++后台开发

后端开发 epoll Linux服务器开发 C++后台开发 户态协议栈

Karmada v1.2发布:开启全文本搜索新纪元

华为云开发者联盟

云计算 调度器 Karmada 全文本搜索 资源解释器

融云 IMKit Web 端上线,带你感受开发效率的参差

融云 RongCloud

企业为什么要部署专属的IM即时通讯软件?

WorkPlus

企业数字化转型加速,选对在线协作工具事半功倍

小炮

实时监控,智能预警,疾控中心的战疫“速度”

博睿数据

智能运维 博睿数据

模块三

Geek_2ce415

数据湖基本架构

五分钟学大数据

数据湖 6月月更

告警消息何去何从?在飞书中飞起来

Rancher

Kubernetes k8s rancher

veImageX演进之路:FPGA HEIF 静图编码服务性能优化_AI&大模型_周强_InfoQ精选文章