想象你开了一家生意爆火的餐厅。后厨里,几位大厨手速惊人,一分钟能颠勺几十次;可所有食材都堆在离灶台很远的大冷库里,灶台和冷库之间只有一条窄窄的传菜通道,一次只能端一盘菜。于是,大厨们常常炒完一道菜,锅都烧红了,下一位食材还没送到——手再快,也快不过那条通道。这条通道的宽度,就是GPU世界里的“显存带宽”。 GPU里有成千上万个计算核心,它们就是那些大厨;显存就是那座冷库;而带宽决定了食材(数据)从仓库运到灶台的速度。你会发现,很多渲染卡顿的场景里,GPU核心并没有偷懒,它们是在“等数据”。这篇文章会用“后厨改造”的视角,带你学会三招:把食材压缩成浓缩块再运(纹理压缩)、把做好的菜打包再送(帧缓冲压缩)、把常用食材按做菜顺序摆到手边(数据布局与缓存优化)。最后,我们还会给后厨装上监控(带宽测量),让你真正找到瓶颈、对症下药。

岗位关联

对AI从业者而言,理解GPU带宽优化意味着你能在不堆硬件的前提下让渲染推理跑得更快、更省电,这是移动端、云渲染与高性能图形管线工程师的核心竞争力。

目录
  1. 可视化演示
  2. 带宽概念认知:窄通道拖垮大厨
  3. 显存访问模式:冷库到灶台的取货路线
  4. 纹理压缩格式:浓缩食材搬运法
  5. 帧缓冲压缩:成品菜打包保温盒
  6. 数据布局优化:托盘分拣与摆位
  7. 缓存利用策略:让热菜留在锅边
  8. 带宽测量诊断:给后厨装上监控
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

动态演示带宽优化的核心机制,通过采集/分析/决策/反馈四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

带宽优化:GPU带 GPU带宽瓶颈与性能影响 纹理压缩格式与选择策略 核心机制可视化 带宽优化整体架构与关键组件

带宽概念认知:窄通道拖垮大厨

你开的餐厅生意突然火了,老板一高兴,多请了三倍的大厨。结果出菜速度不但没变快,后厨反而更乱——因为灶台和冷库之间只有一条窄窄的传菜通道,大厨们炒完一道菜,锅都烧红了,食材还没送到。问题不在人手,在通道。对GPU来说,这条通道就是显存带宽。

在计算机图形学里,带宽指单位时间内从显存搬运到GPU计算核心的数据量,单位是GB/s。渲染一帧画面,要读顶点坐标、要采样纹理、要读写各种缓冲,所有数据都挤在同一条通道上往返。如果显存容量够大、GPU核心也很强,但带宽不够,核心就会陷入“饥饿”状态:算完手上的活就空转,眼巴巴等下一批数据。移动端掉帧、桌面端帧率上不去,很多时候根本不是GPU算不动,而是数据送不到。

带宽由两个硬件参数共同决定:显存的有效传输频率,以及每次传输的位宽。位宽好比通道里能并排开几辆餐车,频率好比每秒发几趟车。二者相乘,再换算成字节,就是带宽:

假设有效传输频率1000MHz、位宽256bit,带宽就是32GB/s。频率不变、位宽翻倍,带宽跟着翻倍;反过来,位宽砍半,带宽立刻掉一半。这就是为什么高端显卡的显存位宽普遍更大——光提高频率是有限的,拓宽“车道”才是硬道理。

所以,优化带宽的第一步是转变思维:GPU跑不满,很可能是“通道”太窄,不是“厨师”太慢。把思路从“多堆核心”转向“让核心少等数据”,后面几节讲的压缩、布局、缓存,全都是朝这个方向使劲。

B=f×w8\displaystyle B = \frac{f \times w}{8}
这个公式说明:带宽等于有效传输频率乘上每次传输位宽,再除以8把bit换算成字节。
  1. w(位宽)每次能并排传多少个bit,就好比传菜通道能并排开几辆餐车。
    w=256 bitw = 256 \ \text{bit}
  2. f(有效传输频率)每秒发几趟“数据餐车”,单位是赫兹(Hz)。
    f=1000 MHz=1000×106 Hzf = 1000 \ \text{MHz} = 1000 \times 10^6 \ \text{Hz}
  3. ÷8(bit转字节)8个bit组成1个字节,把单位统一成Byte。
    B=1000×106×2568=32 GB/sB = \frac{1000 \times 10^6 \times 256}{8} = 32 \ \text{GB/s}

显存访问模式:冷库到灶台的取货路线

如果冷库离灶台有五百米,大厨每次炒菜都要亲自跑一趟,那他一天也炒不了几道菜。现实中后厨的解决办法是分层:冷库旁边设备菜台(L2缓存),灶台手边放手边架(L1缓存和寄存器)。大厨炒菜时只从手边取料,手边缺了再从备菜台补齐,备菜台也没有才去开冷库。数据在GPU里也是这么流动的。

这套体系的效率,取决于“访问模式”。如果程序总是访问靠近的内存地址,或者反复访问刚用过的数据,缓存就能大量命中。前者叫空间局部性,后者叫时间局部性——好比一道菜里要用到的葱姜蒜本来就应该放在同一个托盘里,而上次炒菜剩下的高汤马上还能再用。反之,如果数据东一个西一个,每次都要去冷库翻箱倒柜,代价就大了:一次显存访问要等几百个周期,而缓存命中只要几个周期。

衡量这套体系最直接的方法是算平均访问时间,它是命中与未命中的加权平均:

一个常见优化是“合并访问”:让同一批线程去读相邻地址,这样一次显存事务就能把一整块数据搬回来,而不是每个线程各取各的。就像备菜员按菜谱把食材一次性装盘,而不是让大厨每样调料都跑一趟仓库。想让GPU核心吃饱,就得顺着缓存和显存的脾气走:连续、紧凑、可预测的访问,永远比乱序跳跃高效得多。

T=h×Tcache+(1−h)×Tmem\displaystyle T = h \times T_{cache} + (1 - h) \times T_{mem}
这个公式说明:平均取一次数据的耗时,等于命中缓存的部分走快路、未命中回显存的部分走慢路,两者按比例加权。
  1. h(命中率)所有数据访问中,落在缓存里的比例。
    h=NhitNtotalh = \frac{N_{hit}}{N_{total}}
  2. T_cache(快层延迟)命中时从缓存取数据的耗时,一般只有几个时钟周期。
    Tcache=3∼10 cyclesT_{cache} = 3 \sim 10 \ \text{cycles}
  3. (1-h)(未命中率)需要回显存取数的访问占比。
    1−h=NmissNtotal1 - h = \frac{N_{miss}}{N_{total}}
  4. 加权求和命中部分走快路、未命中部分走慢路的平均耗时。

纹理压缩格式:浓缩食材搬运法

后厨运蔬菜很占地方——一车西兰花只能装几十颗。聪明的做法是先把蔬菜脱水、压成浓缩块,运到灶台再加水还原。GPU里的纹理就是这个思路:纹理是贴在3D模型表面的图片,往往又大又多,直接搬运非常耗带宽,所以GPU会把纹理压缩成紧凑格式存储,采样时由硬件实时解压,对上层开发者透明。

纹理压缩的核心是“块压缩”:把固定大小的像素块(比如4×4)看成一个整体,编码成固定长度的字节。这样压缩率是确定的,硬件解压也快。移动端最常见的ETC2,每个4×4块压缩后固定为8字节;而ASTC更灵活,支持从4×4到12×12的块大小,块越大压缩率越高、质量略降。来看一笔账:

纹理压缩带来的带宽收益非常可观:同样一张1024×1024纹理,用ETC2后从4MB降到0.5MB,采样时GPU只需搬运八分之一的数据。代价是质量——压缩块越小画质越好但占空间越大,这就需要做权衡:主角模型用较小压缩块(如ASTC 6×6),大地面用高压缩块(如ASTC 10×10)。干菜虽然不如新鲜菜水灵,但省下的通道跑起来,整桌菜反而上得更快。

R=16×48=8:1\displaystyle R = \frac{16 \times 4}{8} = 8:1
这个公式说明:一个4×4像素块原始占64字节,ETC2压缩成8字节后,数据量只剩八分之一。
  1. 原始大小4×4=16个像素,每个像素用RGBA8888表示占4字节。
    Draw=16×4=64 BD_{raw} = 16 \times 4 = 64 \ \text{B}
  2. 压缩后大小ETC2将一个4×4块编码为固定8字节。
    Dcompressed=8 BD_{compressed} = 8 \ \text{B}
  3. 压缩率原始大小除以压缩后大小,得到8比1。
    R=64 B8 B=8R = \frac{64 \ \text{B}}{8 \ \text{B}} = 8

帧缓冲压缩:成品菜打包保温盒

食材搬运省下来了,可还有一路开销在“上菜”环节:渲染完成后的画面,也就是帧缓冲(颜色、深度等数据),要写回显存等待显示。这就好比一道道成品菜要从灶台端到传菜口,如果盘子里汤汤水水一路洒,等于白费功夫。帧缓冲压缩干的事,就是把成品菜装进保温盒再端出去——数据先压缩再写回,读回来时再解压,整个过程由硬件完成,开发者无需改代码。

这项技术对移动GPU尤其关键:手机的分辨率越来越高,帧缓冲写回占用的带宽常常是最主要的瓶颈之一。ARM的AFBC、高通的UBWC,都是类似的帧缓冲压缩方案。它们常被设计成无损或视觉无损,部分场景(如深度缓冲)甚至可以稳定省下一半以上的带宽:

需要清醒的是,帧缓冲压缩不是所有内容都能压得很漂亮——遇到颜色剧烈变化的区域,压缩率可能退化甚至达不到无损要求,这时硬件会退回原始格式。所以不要只看纸面参数,最终要用计数器实测带宽收益。保温盒能装多少菜,得真端一趟才知道;但方向是对的:让每一趟传菜都尽量装满有用的数据。

S=Draw−Dcompressed=Draw×(1−r)\displaystyle S = D_{raw} - D_{compressed} = D_{raw} \times (1 - r)
这个公式说明:一次写回省下的带宽等于原始数据量减去压缩后数据量,也就是原始量乘以省下的比例r。
  1. D_raw(原始数据量)未压缩时帧缓冲的字节数。
    Draw=W×H×bppD_{raw} = W \times H \times bpp
  2. D_compressed(压缩后数据量)硬件压缩后实际写回的字节数。
    Dcompressed=Draw×rD_{compressed} = D_{raw} \times r
  3. S(节省的带宽)两者相减,得到每帧写回省下的数据量。
    S=Draw×(1−r)S = D_{raw} \times (1 - r)

数据布局优化:托盘分拣与摆位

外卖出餐快不快,备餐员的摆盘决定一半。如果一道红烧肉的肉、姜、葱分别放在冷库的三个角落,取一趟要跑三回;如果备餐员提前把这道菜的所有食材按使用顺序放进同一个托盘,大厨一次就能拿到手。数据在内存里的排布也是如此——GPU按缓存行(一次固定取64或128字节)搬运数据,如果这一行里都是当前用得上的数据,效率就高。

两个最常用的手法是内存对齐和结构体重组。内存对齐要求把数据按16字节或256字节对齐,避免一个对象跨两个缓存行,否则一次要取两行才凑得齐;结构体重组则把“零散摆放”改成“按需紧凑”。图形学里经典的例子是顶点数据:AoS把所有属性(位置、法线、UV)交错排列,一个顶点挨着一个顶点;SoA则把同一属性连续存放,采样同一批次属性时缓存行利用率更高。衡量效果的核心指标是:

除了摆位,还有“批次合并”:把大量小物体的渲染请求合并成一个大批次,减少重复的状态切换和数据上传开销。这就像把十几桌客人的订单一次性下单给后厨,而不是一桌一桌地催。数据布局优化不改变任何画面的像素,却能让同样一帧画面少走大量冤枉路,属于典型的“看不见但省大钱”的优化。

U=DusefulDline\displaystyle U = \frac{D_{useful}}{D_{line}}
这个公式说明:缓存行利用率等于每次取到的数据里真正有用的字节数除以缓存行总大小。
  1. D_line(缓存行大小)GPU一次从显存取回的最小单位,常见64或128字节。
    Dline=64 BD_{line} = 64 \ \text{B}
  2. D_useful(有用数据)这一趟搬运中,当前渲染真正会用到的字节数。
    Duseful=Nvalid×SeachD_{useful} = N_{valid} \times S_{each}
  3. 相除得利用率越接近1,说明每一趟传菜都装得满满当当。
    U=Duseful64U = \frac{D_{useful}}{64}

缓存利用策略:让热菜留在锅边

客人翻台快的时候,后厨有个小技巧:这桌客人爱吃的蘸料、常点的配菜,直接留在灶台手边,不用每次重新去冷库拿。渲染也一样——某些纹理、顶点缓冲在连续几帧里会被反复使用,如果能让它们“热”在缓存里,就能省下海量显存往返。缓存命中的本质,就是让高频率使用的数据留在离计算尽可能近的地方。

要让缓存更“热”,第一是提高命中率。渲染顺序在这里很关键:想象画家画一面墙,如果先画完全部左半边再画右半边,相邻笔触用的颜料就在手边;如果东一榔头西一棒子,每笔都要重新挤颜料。GPU渲染时按材质/纹理对三角形排序,就能让使用同一纹理的绘制聚在一起,缓存命中率自然上升。第二是理解Tile式渲染——移动GPU把屏幕分成一个个小块(Tile),在片内SRAM上完成一个小块的所有绘制后再整体写回显存,中间结果根本不出门。命中率用这个公式衡量:

Tile式渲染和帧缓冲压缩是天生一对:小块渲染完的片段压缩后写回,带宽占用进一步降低。理解缓存策略后你会发现,很多“卡顿”并不是单次操作慢,而是热数据被反复冷启动——就像每道菜都从冷库重新拿料,后厨再大也忙不过来。把热菜留在锅边,整条流水线才转得起来。

h=NhitNhit+Nmiss\displaystyle h = \frac{N_{hit}}{N_{hit} + N_{miss}}
这个公式说明:缓存命中率等于命中次数除以总访问次数,命中率越高,需要回显存取数据的次数就越少。
  1. 分子(命中次数)在缓存中找到数据的访问次数。
    NhitN_{hit}
  2. 分母(总访问次数)命中加未命中的全部访问。
    Nhit+NmissN_{hit} + N_{miss}
  3. 比值命中率越接近1,带宽压力越小。
    h=NhitNhit+Nmissh = \frac{N_{hit}}{N_{hit} + N_{miss}}

带宽测量诊断:给后厨装上监控

后厨改造得再热闹,也得有数据说话:每天到底从冷库搬了多少吨食材?传菜通道最堵的是哪几个时段?同理,GPU优化也离不开测量。没有测量,你分不清卡顿是核心算不完,还是数据送不到。现代GPU都内置硬件性能计数器,能直接读出显存读写了多少字节,这就是带宽优化的“后厨监控”。

有了字节数,再结合渲染耗时,就能算出实测带宽:

拿到数据后怎么判断瓶颈?看两个数:GPU核心利用率和带宽占用率。如果核心利用率只有五六成,而带宽占用率已经飙到九成以上,那就是典型的带宽受限——通道堵死了,核心只能饿着等。工具链上,PC端用NVIDIA Nsight Graphics,移动端用Perfetto或高通Snapdragon Profiler,都能逐帧看带宽消耗。后厨装上监控之后,每一趟传菜都清清楚楚:到底是食材太多(纹理过大)、路太绕(布局不佳),还是保温盒没用上(没开帧缓冲压缩)?对着数据做优化,才不是拍脑袋。

B=DtotalTframe\displaystyle B = \frac{D_{total}}{T_{frame}}
这个公式说明:实测带宽等于一帧渲染期间总的显存数据传输量除以渲染耗时,拿它和硬件峰值带宽对比就能判断余量。
  1. D_total(传输总量)计数器统计的显存读写总字节数,包括纹理、顶点、帧缓冲等。
    Dtotal=Dread+DwriteD_{total} = D_{read} + D_{write}
  2. T_frame(帧耗时)渲染一帧画面的总时间,单位秒。
    Tframe=0.016 sT_{frame} = 0.016 \ \text{s}
  3. 两者相除得到平均每秒搬运的数据量。
    B=DtotalTframe GB/sB = \frac{D_{total}}{T_{frame}} \ \text{GB/s}

AI 应用场景

移动端游戏渲染优化

阶段:渲染管线性能优化

解决的问题:手机游戏画面越来越精细,但移动GPU的显存带宽远小于桌面显卡。传统做法是直接堆放高分辨率纹理,导致带宽耗尽、发热降频、帧率不稳。利用纹理压缩(ETC2/ASTC)加帧缓冲压缩,可以把每帧的显存搬运量削减一半以上,续航和流畅度同时提升。

具体案例:某开放世界手游在骁龙平台上帧率总在40fps徘徊,用Snapdragon Profiler一测发现带宽占用率95%而GPU核心利用率只有55%。美术团队把主角贴图从未压缩格式换成ASTC 6×6,地面换成8×8,再开启AFBC帧缓冲压缩,带宽占用降到了62%,帧率稳定在60fps,机身温度也降了3度。

大型场景流式加载的带宽预算

阶段:数据加载与调度

解决的问题:开放世界和云渲染场景中,玩家移动时地形、建筑、贴图要持续从硬盘或显存加载。传统“整图加载”既占显存又占带宽。通过纹理压缩控制数据体积、顶点布局SoA化提升缓存利用率,再按可见性分块加载,可以显著降低瞬时带宽峰值,避免快速旋转视角时的卡顿。

具体案例:某云游戏平台在低带宽服务器上跑高画质赛车游戏,通过ASTC压缩场景纹理、把顶点缓存按SoA重排并合并批次,实测每帧传输数据从580MB降到310MB,多人同屏时画面抖动明显减少。

桌面渲染管线的性能诊断

阶段:性能分析与调优

解决的问题:桌面GPU带宽大,但面对光追、超清纹理、高刷新率时依然可能带宽受限。传统开发者习惯“加显存”“换显卡”,但真正的瓶颈可能藏在数据布局和缓存命中率上。用性能计数器定位后,做纹理压缩选择和数据布局优化,不必升级硬件就能跑满核心。

具体案例:某建筑设计可视化软件在RTX 4060上导出4K漫游视频吃力,Nsight Graphics显示带宽占用76%、核心利用率仅58%。将植被纹理换成BC7压缩、把分散的顶点属性重组为连续缓冲后,带宽占用降到44%,导出速度提升约1.8倍。

Python 演示

python53 行
# -*- coding: utf-8 -*-"""缓存访问模式模拟器:演示顺序/跳变/合并访问对命中率的影响"""  class CacheSim:    """极简FIFO缓存模拟器"""     def __init__(self, line_count=4, line_size=8):        self.line_count = line_count    # 缓存行数        self.line_size = line_size      # 缓存行大小(字节)        self._tags = []                # 缓存行标记(起始地址)        self.hit_count = 0        self.miss_count = 0     def access(self, address):        """访问一个字节地址,返回是否命中"""        tag = address // self.line_size        if tag in self._tags:            self.hit_count += 1            return True        # 未命中:按FIFO替换一个缓存行        if len(self._tags) >= self.line_count:            self._tags.pop(0)        self._tags.append(tag)        self.miss_count += 1        return False     def hit_rate(self):        total = self.hit_count + self.miss_count        return (self.hit_count / total) if total else 0.0  def run_pattern(name, addresses):    sim = CacheSim()    for addr in addresses:        sim.access(addr)    print("%s: 命中率 %.1f%%" % (name, sim.hit_rate() * 100))  def main():    # 连续访问相邻地址:空间局部性好    sequential = [i * 4 for i in range(200)]    run_pattern("顺序访问(局部性好)", sequential)    # 每次跨很大间隔访问:局部性差    jumping = [i * 64 for i in range(200)]    run_pattern("跳变访问(局部性差)", jumping)    # 按缓存行整块访问:合并访问    block = [i * 8 for i in range(200)]    run_pattern("连续块访问(合并)", block)  if __name__ == "__main__":    main()
目的:用几十行代码模拟GPU缓存的访问行为,直观对比不同数据布局下的命中率差异,这正是“数据布局优化”背后的基本原理。
  1. tag = address // self.line_size把字节地址映射到缓存行号,如同把食材按“托盘”分组。
  2. if tag in self._tags:查缓存是否已有此行,命中就返回True。
  3. self._tags.pop(0)` 和 `self._tags.append(tag)未命中时按FIFO踢掉最老的缓存行,类似备菜台放不下时清走最久没动的托盘。
  4. run_pattern("顺序访问(局部性好)", sequential)顺序访问相邻地址,模拟空间局部性好的数据布局。
  5. run_pattern("跳变访问(局部性差)", jumping)跳变访问,模拟数据分散时的缓存灾难。
  6. hit_rate()计算命中率,对应正文中“命中率越高带宽压力越小”的判断方法。

常见误区

误区游戏掉帧、渲染卡顿,第一反应就是“显卡不够好”,换一张核心更多、显存更大的显卡就能解决。每次都把带宽问题归结为硬件预算问题,从不看数据是怎么搬运的。

正解如果瓶颈是显存带宽,换更高端的显卡反而可能更糟——高端卡核心更多,单位时间内“想吃”的数据量更大,传菜通道虽然宽了一点,但大厨们饿得更快。真正该做的是减少数据搬运量:纹理压缩、帧缓冲压缩、数据布局优化,让同样的通道送更多有用数据。先用profiler实测,再决定是改软件还是换硬件。

为何常见:人们习惯用“硬件性能决定一切”的直觉思考问题,而且升级硬件是最省事的方案,不需要理解底层的访问模式和数据结构。

误区压缩就是有损,有损就意味着糊成一片。开发者担心ASTC、ETC2会让游戏画面产生肉眼可见的色块和模糊,于是坚持使用未压缩的RGBA纹理,宁可多耗带宽。

正解基于块的纹理压缩算法经过数十年优化,在常见压缩率下(如ETC2的4bpp、ASTC 6×6)对画质影响极其微小,很多情况下连专业美术都难以分辨。更重要的是,带宽节省带来的高帧率、高分辨率,对观感的提升远大于纹理压缩带来的轻微质量损失。实际项目中还可以做分级:主角等关键模型用低压缩率,远处地面用高压缩率。

为何常见:把“有损压缩”和“画质崩坏”划等号,忽略了压缩率可调、块效应可控的事实,属于对算法能力的刻板印象。

误区既然缓存命中能省带宽,那就把所有数据都塞进缓存,或者无脑加大缓存,把命中率冲得越高越好。把命中率当成了终极优化目标本身。

正解命中率高通常代表不错的局部性,但盲目追求命中率可能带来反效果:缓存容量有限,塞太多冷数据会把热数据挤出去(缓存污染);而且缓存本身也有访问延迟和功耗。正确的目标不是追求命中率数字,而是降低整体渲染耗时的带宽开销——适度布局、按需预取、关键资源复用,让有效数据尽量连续流动,比单纯“堆命中”更健康。

为何常见:初学者看到“命中率高=省带宽”就认为它是线性正相关的唯一目标,忽略了缓存容量和替换策略对整体性能的复杂影响。

误区游戏跑得流畅、帧率挺高,就认为带宽优化已经做得很好,不需要再关注。把“不卡顿”等同于“资源效率高”。

正解不卡顿只说明结果能接受,不代表通道利用率健康。可能GPU核心一直在等数据,只是等待时间恰好被帧预算掩盖;也可能带宽占用率已接近90%,一旦场景变复杂(多角色、高分辨率)就会立刻爆掉。用性能计数器看看核心利用率和带宽占用率的比例,才能发现隐性瓶颈——未来的每一帧优化,都建立在现状被准确测出来的基础上。

为何常见:人的感知是滞后的,只有明显丢帧才能察觉问题;带宽作为隐形资源,不像FPS一样每天摆在眼前,容易成为“看不见的盲区”。

面试题

Q1. 在GPU渲染中,“显存带宽”最准确的含义是?

单选题 · easy

  • A.显存的存储总容量
  • B.单位时间传输数据量← 正确答案
  • C.GPU核心运算速率
  • D.压缩后纹理大小

答案:B。带宽是“通道有多宽”的概念,衡量单位时间内能搬运的数据量,对应传菜通道的吞吐能力。容量大小(A)是仓库有多大,核心速率(C)是厨师手多快,纹理大小(D)只是数据体积,都和带宽含义不同。

Q2. 缓存命中率高,对带宽优化最直接的帮助是?

单选题 · easy

  • A.减少显存读写的次数← 正确答案
  • B.增加纹理的分辨率
  • C.提高GPU核心的频率
  • D.减少顶点数据的量

答案:A。缓存命中等于数据在备菜台就找到了,不用回冷库翻找,自然减少了显存读写的次数、省下带宽。它不会改变纹理分辨率、核心频率或顶点数量,那些是另一层面的问题。

Q3. 一个4×4像素块用RGBA8888存储(每像素4字节),原始大小是多少字节?

单选题 · easy

  • A.占8字节
  • B.占16字节
  • C.占64字节← 正确答案
  • D.占48字节

答案:C。4×4像素块共16个像素,每个像素4字节,16×4=64字节。这也是理解纹理压缩率的基础:ETC2把64字节压成8字节,得到8:1的压缩率。

Q4. ETC2纹理压缩格式中,每个4×4像素块压缩后占用多少字节?

单选题 · mid

  • A.占4字节
  • B.占8字节← 正确答案
  • C.占16字节
  • D.占64字节

答案:B。ETC2固定把每个4×4块编成8字节,平均每像素只需2bit(4bpp)。A的4字节对应更激进的压缩假设,C的16字节更接近ASTC大块输出,D则是未压缩的原始大小。

Q5. 以下哪些做法能有效减少显存带宽消耗?

多选题 · mid

  • A.开启ASTC纹理压缩← 正确答案
  • B.开启帧缓冲压缩← 正确答案
  • C.不断提高屏幕分辨率
  • D.优化数据布局提高命中← 正确答案

答案:ABD。纹理压缩和帧缓冲压缩都直接减少传输数据量,数据布局优化提升缓存命中率从而减少显存往返。提高分辨率(C)反而会让每一帧需要处理更多像素、更多带宽,与优化方向背道而驰。

Q6. “空间局部性”描述的是哪种访问模式?

单选题 · mid

  • A.刚用过的数据紧接着重复使用
  • B.相邻内存地址的数据被一起使用← 正确答案
  • C.数据存储越久读取速度越快
  • D.显存容量越大则带宽越宽

答案:B。空间局部性指访问了一个地址后,附近地址的数据也很快被用到——像同一托盘里的食材被连续取用。A描述的是时间局部性;C和D把存储时间、容量与带宽混为一谈,都不属于局部性原理。

Q7. 带宽公式B=f×w÷8中,w的单位是什么?

单选题 · mid

  • A.字节Byte
  • B.比特bit← 正确答案
  • C.频率Hz
  • D.兆赫MHz

答案:B。w表示显存控制器一次数据传输的位宽,单位是bit;除以8是为了把bit换算成Byte。A(字节)是除以8之后的结果单位,C和D是频率f的单位,不是位宽。

Q8. 关于帧缓冲压缩,下列说法正确的是?

多选题 · hard

  • A.对应用透明由硬件完成← 正确答案
  • B.移动GPU常用AFBC技术← 正确答案
  • C.必然导致画质严重下降
  • D.减少颜色缓冲写回带宽← 正确答案

答案:ABD。帧缓冲压缩由GPU硬件在写回显存时自动完成,应用层完全无感,ARM AFBC和高通UBWC是典型实现,能明显减少颜色/深度缓冲的写回带宽。它通常设计为无损或视觉无损,用“必然严重下降”(C)来概括是不对的。

Q9. 判断渲染管线是否为带宽受限,最可靠的指标组合是?

单选题 · hard

  • A.核心利用率低且显存带宽近峰值← 正确答案
  • B.核心利用率高且显存带宽余量大
  • C.纹理压缩率已经达到最高
  • D.缓存命中率等于百分之零

答案:A。带宽受限的典型特征是“核心饿着等数据”:GPU核心利用率低,而显存带宽占用率接近峰值,说明通道堵死了。B说明核心很忙且带宽还有余量,不是带宽瓶颈;C和D只是相关现象,不能独立作为判断依据。

Q10. 移动端Tile式渲染的优势包括哪些?

多选题 · extreme

  • A.片内完成一屏绘制再写回← 正确答案
  • B.大幅减少中间结果来回← 正确答案
  • C.反而增加了带宽消耗
  • D.配合帧缓冲压缩效果更好← 正确答案

答案:ABD。Tile式渲染把屏幕切成小块,在片内SRAM上完成所有绘制后再整体写回,中间的深度/颜色结果不出门,大幅减少显存往返,也因此和帧缓冲压缩天然搭配。它显然是减少而非增加带宽消耗,所以C错误。