想象有一座中央菜谱库,里面存放着几十家分店共享的招牌菜配方——这就是“模型参数”。每位厨师一边照着菜谱做菜,一边琢磨改进建议:“盐减半勺”“火候再加十秒”,这些建议就是“梯度”。如果采用古老的“大食堂模式”,所有厨师必须举着建议单在菜谱库门口集合,等最慢的那位到齐,总厨才一次性把所有人的建议抄进新菜谱——这是“同步SGD”:稳当,但全队速度被最慢的人锁死。于是有一家连锁集团改了店规:谁先到,谁先改!任何一位厨师的建议送到,总厨立刻誊写更新,并广播新菜谱。这就是“异步SGD”:吞吐飞快,却埋下一个隐患——某位厨师出发时照着的是三个版本前的旧菜谱,等建议千里迢迢送到,菜谱已被改了好几版,这条“过时建议”(Stale Gradient)该不该听?该怎么听?本文就用这套厨房故事,把异步SGD的原理、风险、对策与应用场景讲个透。

岗位关联

掌握异步SGD的原理与工程取舍,是设计大规模分布式训练系统的核心能力,能帮你在训练提速、集群容错和收敛质量之间做出正确的工程决策。

目录
  1. 可视化演示
  2. 数据并行基础
  3. 同步模式回顾
  4. 异步更新原理
  5. 梯度延迟风险
  6. 陈旧梯度处理
  7. 适用场景选择
  8. 工程实践要点
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示异步参数更新、梯度延迟问题与收敛性对比,切换模式理解异步SGD核心原理与权衡。

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

异步参数更新流程 各worker独立拉取参数、计算梯度并立即推送,无需等待同步屏障 θ ← θ - η·g_i 参数服务器收到梯度后立即更新,消除等待时间提升吞吐

数据并行基础

中央菜谱库要同时服务几十家分店,总厨分身乏术,总不能把几百道菜的订单都搬到一个厨房里。聪明的连锁集团想出一个办法:每家分店都完整拷贝一份最新菜谱,各自接待自己的客人;打烊后,每家店对照自己的待客经验,独立写一条“今天哪道菜该改进”的建议。这个场景,就是分布式训练里最基础的“数据并行”。

在数据并行框架下,完整训练集被切成互不相交的若干份,分给 N 个 GPU(也就是分店厨师)。每个 worker 手里都有一份模型参数的本地副本,用自己那块数据跑前向和反向传播,独立算出梯度。注意这里每家店的计算互不依赖,只有“建议”需要送给总厨汇总。

第 i 个 worker 的数学动作如下:

这份建议只代表一家分店的局部改良经验,优点是每家店都能闷头干活、天然并行;缺点是它只看了全局数据的一小块,若不做汇总就单独采用,容易偏听偏信。把建议汇总起来究竟怎么用,正是“同步”与“异步”两条路的分岔口。

gi=∇L(wt;Bi)g_i = \nabla L(\mathbf{w}_t; \mathcal{B}_i)
通俗地说:第 i 位厨师(worker)拿着当前版本菜谱 w,对着自己的订单(数据批次 B)算出一份改进建议 g。
  1. 梯度记号(g_i)第 i 个 worker 算出的梯度向量,像一位厨师写下的建议清单。
    gig_i
  2. 梯度算子(\nabla L)损失函数 L 的梯度,即“找出改进方向的手电筒”。
    ∇L\nabla L
  3. 当前参数(\mathbf{w}_t)第 t 版菜谱,所有建议都以它为基准提出。
    wt\mathbf{w}_t
  4. 数据批次(\mathcal{B}_i)第 i 个 worker 分到的训练数据切片,相当于它今天看到的订单。
    Bi\mathcal{B}_i

同步模式回顾

老派大食堂的经营哲学是“齐步走”:总厨黄历一翻,所有厨师必须在同一时刻把建议单立在桌上,等最后一位气喘吁吁赶到,才轮流誊写更新菜谱。这个“必须等人齐”的关卡,在同步 SGD 里被称为同步屏障(barrier)。

技术上,N 个 worker 各自算完本地梯度后,全部卡在屏障处等待;等 N 份梯度都到齐,参数服务器把它们取平均,再乘上学习率,统一更新一次全局参数。因为每一步都弥漫着集体主义精神,更新方向稳定,数学性质好分析。它的标准更新式是:

但老派模式的代价也很现实:队伍的前进速度永远被最慢的厨师锁死。集群一大,机器性能参差,偶尔冒出的慢节点(straggler)会把整体训练拖成“三分钟做饭,十分钟等人”。这种损耗,正是异步改革要解决的痛点。

wt+1=wt−η⋅1N∑i=1Ngi\mathbf{w}_{t+1} = \mathbf{w}_t - \eta \cdot \frac{1}{N} \sum_{i=1}^{N} g_i
意思就是:总厨把 N 位厨师的建议先取平均,乘以打折系数,再统一改进一次菜谱。
  1. 参数版本(\mathbf{w}_t)更新前的菜谱版本,\mathbf{w}_{t+1} 是更新后的新菜谱。
    wt+1=wt−…\mathbf{w}_{t+1} = \mathbf{w}_t - \ldots
  2. 平均操作(\frac{1}{N}\sum)把 N 位厨师的建议取平均,先民主后动手。
    1N∑i=1Ngi\frac{1}{N}\sum_{i=1}^{N}g_i
  3. 学习率(\eta)总厨对平均建议的打折系数,决定一次改多大的刀。
    η\eta
  4. 减号沿梯度的反方向调整参数——既然说太咸,就减盐。
    −η⋅1N∑i=1Ngi- \eta \cdot \frac{1}{N}\sum_{i=1}^{N}g_i

异步更新原理

改革派总厨一拍桌子:把“等人齐”的规矩撕掉!新店规只有四个字——先到先改。无论哪家分店的建议先送到,值班总厨当场誊写进菜谱,并立刻把新版本广播出去,其他厨师照旧按自己的节奏做菜。

实现上需要一位“中央菜谱库”管理员,也就是参数服务器(Parameter Server)。每个 worker 周期性从服务器拉取(pull)最新参数到本地缓存,用这版参数算出梯度后推(push)给服务器;服务器收到哪条,就用哪条更新,不设同步屏障。这个“谁先到谁先改”的机制,就是异步 SGD 的核心。服务器侧的动作可以写成:

对照同步与异步:同步是“N 条建议取平均,改一次”;异步是“来一条改一条,改 N 次”。异步把一次集体会议拆成 N 次即时决策,吞吐自然高出一大截。但聪明的你或许已经察觉:那位厨师出发前抄的菜谱,和总厨现在手里的菜谱,真的是同一版吗?隐患就此埋下。

w←w−η⋅gi\mathbf{w} \leftarrow \mathbf{w} - \eta \cdot g_i
参数服务器收到第 i 位厨师的建议,当场就用它改一次菜谱,不等待任何人。
  1. 就地更新(\leftarrow)服务器收到哪位厨师的建议,立刻拍板修改菜谱。
    ←\leftarrow
  2. 单条梯度(g_i)不再等平均,一条建议也能推动更新。
    gig_i
  3. 学习率(\eta)每次采纳的力度,异步场景下常常调小一些以对冲噪音。
    η\eta

梯度延迟风险

清晨,厨师老张照着一份菜谱出了门,花一天时间研究“盐减半”的改良方案;晚上赶到菜谱库,赫然发现白天菜谱已被连改三版。他手里这份方案,是基于旧菜谱算出来的——这就是陈旧梯度(Stale Gradient)。

形式化地说,老张计算梯度时读到的参数是 \mathbf{w}_{t-3},而它真正被采纳时全局参数已经是 \mathbf{w}_t,中间隔着 3 次别人的更新。我们把 3 这个数字叫梯度延迟 τ(staleness)。它不是因为网络慢才出现,而是“各读各的、并发交错”这种异步节奏天生的副产物。带延迟的异步更新式是:

把过期梯度直接当新鲜梯度使用,数学上会产生偏差:更新方向的真实期望已不属于当前损失地形。延迟越大、占比越高,收敛过程就越像一家沿用数版旧菜谱的连锁店,每家分店各改各的,最后菜的味道可能离标准配方越来越远,严重时甚至震荡发散。

wt+1=wt−η⋅gi(wt−τ)\mathbf{w}_{t+1} = \mathbf{w}_t - \eta \cdot g_i(\mathbf{w}_{t-\tau})
总厨用一份基于旧菜谱算出的建议,去改当前最新版本的菜谱——方向可能已经不对了。
  1. 旧时刻参数(\mathbf{w}_{t-\tau})厨师抄写菜谱时的版本,距今已过了 τ 次修改。
    wt−τ\mathbf{w}_{t-\tau}
  2. 延迟量(\tau)该梯度过期了多少个版本,衡量“建议的新鲜度”。
    τ\tau
  3. 过期梯度(g_i(\mathbf{w}_{t-\tau}))这份建议是基于旧菜谱算出来的。
    gi(wt−τ)g_i(\mathbf{w}_{t-\tau})
  4. 作用到当前参数(\mathbf{w}_t)把过期建议用到新菜谱上,偏差由此产生。
    wt−η⋅gi(wt−τ)\mathbf{w}_t - \eta \cdot g_i(\mathbf{w}_{t-\tau})

陈旧梯度处理

总厨面对满天飞的过期建议,定下三条采纳细则:第一,越旧的建议,采纳时打的折扣越大;第二,建议幅度太离谱的直接限幅;第三,过期太多的一律扔进垃圾桶。这三条,正好对应陈旧梯度处理的三大常用武器:延迟感知加权、梯度裁剪、阈值丢弃。

武器一:延迟感知加权——给每条梯度乘一个随 τ 衰减的系数 α(τ),τ=0 时权重为 1,τ 越大权重越小,常见形式有 1/(1+τ) 或指数衰减 e^{-τ}。武器二:梯度裁剪——把梯度的范数限制在预设阈值内。武器三:阈值丢弃——超过最大延迟 τ_max 的更新直接拒绝。加上加权后的更新式变成:

这三招让总厨既能享受异步的高吞吐,又能给“不新鲜”的建议装上消音器。总结成一句话:听,但别全听;改,但别乱改。过期建议不是毒药,只要掌控好采纳的度,厨房依旧能热火朝天而不翻车。

wt+1=wt−η⋅α(τ)⋅gi(wt−τ)\mathbf{w}_{t+1} = \mathbf{w}_t - \eta \cdot \alpha(\tau) \cdot g_i(\mathbf{w}_{t-\tau})
总厨在采纳前先看一眼“新鲜度标签”:越旧的建议,抄进菜谱时打得折扣越大。
  1. 新鲜度系数(\alpha(\tau))延迟 τ 越大,采纳权重越小。
    α(τ)\alpha(\tau)
  2. 典型衰减函数如 \alpha(\tau)=\frac{1}{1+\tau},把延迟映射成 0 到 1 之间的折扣。
    α(τ)=11+τ\alpha(\tau)=\frac{1}{1+\tau}
  3. 折扣后的建议新学习率等于原学习率乘上折扣。
    η⋅α(τ)⋅gi(wt−τ)\eta \cdot \alpha(\tau) \cdot g_i(\mathbf{w}_{t-\tau})
  4. 修正后的更新式完整写出加权后的异步更新。
    wt+1=wt−η⋅α(τ)⋅gi(wt−τ)\mathbf{w}_{t+1} = \mathbf{w}_t - \eta \cdot \alpha(\tau) \cdot g_i(\mathbf{w}_{t-\tau})

适用场景选择

异步店规是不是放之四海皆准?当然不是。快餐连锁追求出餐速度,客人络绎不绝(数据量大),中央菜谱库必须“先到先改”才能跟上节奏;而高档私房菜讲究每道菜都是艺术品(收敛质量要求极高),主厨宁可慢一点,也要确保每步调整都基于最新状态。

技术层面看,异步 SGD 的甜点位是:其一,几百上千卡的大集群,同步屏障的等待损耗被放大到不可接受;其二,worker 算力或网络异构明显,总有慢节点拖后腿;其三,训练任务需要容错,节点频繁加入退出。反过来,小规模、同构、对收敛路径稳定性极为敏感的任务,用同步或折中方案反而更稳。

工程上可以这样对照选型:集群越大、异构越严重、容错需求越高,越倾向异步;反之则倾向同步。此外还有“同步折中方案”——例如给同步流程配备备份 worker、做梯度累积,把两者优点糅合。这提供了一个连续的光谱,而不是非黑即白的选择题。

选同步还是异步,本质上是在“新鲜度”和“速度”之间做权衡:上千人的食堂必须流水线异步出餐,十人的私房菜品则要保证每道菜都精准。理解自己的客流量(数据规模)和上菜瓶颈(慢节点),才能定下合适的店规。

工程实践要点

定了异步店规,还要有精细的值班台账。经验丰富的总厨每天盯着墙上的“建议新鲜度仪表盘”,一旦某家分店送来的建议过期太离谱,立刻预警并调整节奏。这在工程上对应 staleness 监控——把参数版本号当时间,把版本差当仪表读数。

三项常用工程手段。第一,版本差监控:为每次推送记录 τ,并计算集群平均延迟,作为整体健康度指标。

第二,备份 worker(backup worker):在同步主流程外预启动少量备用 worker,某个节点太慢时让备份直接顶上,既保留同步的确定性,又缓解慢节点拖累。第三,混合异步:热门参数走同步、冷门参数走异步;或者本地累积若干条梯度再推送,缩小更新之间的版本差距。

异步是一匹快马,但再快的马也需要好骑手。监控、备份、混合,就是控制缰绳的三根手指。只要管理得当,异步 SGD 能同时交出吞吐与收敛两份漂亮成绩单,这也是它在现代大模型训练中屡屡登场的原因。

τˉ=1K∑k=1Kτk\bar{\tau} = \frac{1}{K} \sum_{k=1}^{K} \tau_k
把 K 位厨师最近一次建议的过期版本数加起来求平均,数值越大,说明菜谱库越混乱。
  1. 平均延迟(\bar{\tau})整个集群当前“菜谱新鲜度”的综合指标。
    τˉ\bar{\tau}
  2. 求和与平均把 K 个 worker 各自的延迟累加后除以 K。
    1K∑k=1Kτk\frac{1}{K}\sum_{k=1}^{K}\tau_k
  3. 每个延迟(\tau_k)第 k 个 worker 最近一次梯度推送时过期的版本数。
    τk\tau_k

AI 应用场景

电商推荐 CTR 模型的大规模训练

阶段:模型训练与优化

解决的问题:广告推荐场景有上千亿特征、上千个 worker。传统同步 SGD 每轮都要等全集群到齐,任何一张卡抖动都会让整体吞吐崩塌。异步 SGD 让每个 worker 各自推送梯度,把训练吞吐提升 3-5 倍,慢节点不再卡死全局。

具体案例:某电商平台用参数服务器 + 异步 SGD 训练 CTR 预估模型,每日处理百亿级样本;通过延迟感知加权和梯度裁剪,模型每小时更新一次,在保持 AUC 不降的前提下大幅缩短训练周期。

大语言模型预训练的容错训练

阶段:分布式预训练

解决的问题:千卡级 LLM 训练中单卡故障是常态,同步模式一旦有节点掉线,全队都会停滞等待重启。异步 SGD 配合备份 worker,让故障节点背后的计算任务由替补继续推进,训练节奏不被频繁打断。

具体案例:某公司训练百亿参数模型时,用异步 SGD + 版本号监控 + 定期 checkpoint,将节点故障导致的整体停摆时间降低了约 70%,同时通过 stale 梯度衰减保证收敛质量。

广告点击率在线学习

阶段:在线学习 / 增量训练

解决的问题:广告系统的点击日志以流式不断到达,全量重训跟不上热点变化节奏。异步 SGD 让新数据一到就能驱动一次参数更新,模型持续吸收最新用户反馈。

具体案例:广告平台每 5 分钟用新增的曝光点击数据做一批异步参数更新,出价模型能够及时捕捉突发节假日流量变化,实时点击率预估的 AUC 提升明显。

Python 演示

python81 行
import mathimport random  class ParamServer:    """中央菜谱库:维护一份全局菜谱(权重向量)"""     def __init__(self, dim=4):        self.w = [0.0] * dim        self.version = 0  # 菜谱被改了几版     def update(self, grad, lr, stale):        alpha = 1.0 / (1.0 + stale)   # 越旧建议,折扣越大        for i in range(len(self.w)):            self.w[i] -= lr * alpha * grad[i]        self.version += 1     def pull(self):        return self.w[:], self.version  class Worker:    """分店厨师:用自己的订单计算改进建议"""     def __init__(self, x, y, pid):        self.x = x        self.y = y        self.pid = pid     def grad(self, w):        n = len(self.y)        g = [0.0] * len(w)        for xi, yi in zip(self.x, self.y):            pred = sum(a * b for a, b in zip(w, xi))            err = pred - yi            for j in range(len(w)):                g[j] += 2.0 * err * xi[j] / n        return g  def gen_data(n, seed):    random.seed(seed)    x = [[1.0, random.uniform(-1, 1), random.uniform(-1, 1),          random.uniform(-1, 1)] for _ in range(n)]    y = [2.0 * xi[1] - 1.5 * xi[2] + 0.4 * xi[3] for xi in x]    return x, y  def async_train(server, workers, epochs, lr=0.05):    cache_w = [server.pull()[0] for _ in workers]    cache_v = [0] * len(workers)    for _ in range(epochs):        k = random.randrange(len(workers))        stale = server.version - cache_v[k]        g = workers[k].grad(cache_w[k])        server.update(g, lr, stale)        cache_w[k], cache_v[k] = server.pull()    return server.pull()[0]  def sync_train(server, workers, epochs, lr=0.05):    for _ in range(epochs):        grads = [w.grad(server.pull()[0]) for w in workers]        avg = [sum(g[j] for g in grads) / len(grads)               for j in range(len(grads[0]))]        server.update(avg, lr, 0)    return server.pull()[0]  if __name__ == "__main__":    x, y = gen_data(400, 42)    workers = [Worker(x[i * 100:(i + 1) * 100], y[i * 100:(i + 1) * 100], i)               for i in range(4)]     sa = ParamServer()    wa = async_train(sa, workers, 200, lr=0.05)    print("async w =", [round(v, 3) for v in wa])     sb = ParamServer()    wb = sync_train(sb, workers, 200, lr=0.05)    print("sync  w =", [round(v, 3) for v in wb])
目的:用餐厅比喻模拟异步 SGD 与同步 SGD 的参数更新过程,展示“先到先改 + 过期折扣”如何逼近理想参数。
  1. alpha = 1.0 / (1.0 + stale) # 越旧建议,折扣越大实现延迟感知加权:建议越旧,采纳力度越小。
  2. stale = server.version - cache_v[k]用参数版本号之差计算这条梯度过期了几版。
  3. g = workers[k].grad(cache_w[k])基于本地缓存的旧参数计算梯度,这正是异步的本质。
  4. server.update(g, lr, stale)参数服务器收到梯度立即更新,不等其他 worker。
  5. cache_w[k], cache_v[k] = server.pull()更新后立刻拉取最新菜谱和版本号。
  6. grads = [w.grad(server.pull()[0]) for w in workers]同步模式等所有 worker 到齐再取平均。

常见误区

误区异步省掉了等待时间,单位时间更新次数更多,训练损失下降一定比同步快。

正解吞吐高不代表收敛快。每次异步更新用的都是过期梯度,方向有偏差;当 staleness 累积到一定程度,损失下降会变慢甚至震荡。就像一群厨师各拿旧菜谱乱改,建议互相打架,菜反而越做越怪。

为何常见:直观上“单位时间更新次数多 = 进步快”,忽略了梯度质量这一关键变量。

误区梯度陈旧是传输太慢导致的,升级到 RDMA 或 InfiniBand 就能彻底消除。

正解staleness 的本质是“读参数”与“写参数”并发交错:A 读到参数开始计算,这段时间里 B 推了十次更新,即便网络零延迟,A 的建议依然是旧版本算出的。高速网络只能缩小平均 τ,无法消除它。

为何常见:把“旧参数”问题误认为“旧传输”问题,归因错到了基础设施。

误区反正都是并行更新,异步 SGD 的统计效果和同步 SGD 但 batch size 更大差不多。

正解同步大 batch 用的都是最新参数下的梯度,期望无偏;异步 SGD 每条梯度都是历史参数下的产物,数学上 E[g(w_{t-τ})] ≠ ∇L(w_t),更新是有偏的。两者统计性质不同,不能互相替代。

为何常见:只看到相似的计算图,忽略了参数版本是否一致这一关键区别。

误区既然异步快,那就完全放弃同步屏障,开足马力纯异步训练。

正解工程上往往采用备份 worker、周期性同步点、梯度累积等混合手段。纯异步在超大规模且超参不当的情况下,收敛发散风险显著升高。好骑手既要马跑得快,也要缰绳握得住。

为何常见:追求极致速度,忽略了稳定性约束和实际部署中的故障率。

面试题

Q1. 异步SGD相比同步SGD的核心区别是?

单选题 · easy

  • A.worker每次更新不用等待其他worker到齐← 正确答案
  • B.使用更大的数据批次来提升训练效率
  • C.完全不需要计算梯度就能完成更新
  • D.由单台机器独立完成全部训练任务

答案:A。异步 SGD 的“先到先改”让参数服务器收到一条梯度就立即更新,而同步 SGD 必须等所有 worker 到齐。B 的 batch size 与同步异步无关;C 荒谬;D 是单机训练,都不是核心区别。

Q2. 同步SGD的主要痛点是什么?

单选题 · easy

  • A.同步屏障让整体速度被最慢节点拖累← 正确答案
  • B.梯度计算本身会产生额外的系统开销
  • C.无法使用GPU等加速卡来并行计算
  • D.参数更新频率过高导致模型不断发散

答案:A。同步 SGD 的屏障好比大食堂等最慢的厨师到齐才开饭,木桶效应让全队被 straggler 锁死。B 不是同步独有;C 错误;D 是异步更常见的风险。

Q3. 什么是Stale Gradient(陈旧梯度)?

单选题 · easy

  • A.数值大小超出预设范围的异常梯度
  • B.基于过期的旧版本参数算出的梯度← 正确答案
  • C.在训练过程中被直接丢弃的梯度
  • D.多个worker计算出的梯度的平均值

答案:B。陈旧梯度指厨师照着旧菜谱算出的建议,关键在“参数版本旧”而非数值异常或传输时长。A 是异常梯度,C 是被丢弃的对象,D 是同步汇总结果,均不符合概念。

Q4. 参数服务器收到worker推送的梯度后,异步SGD会怎么做?

单选题 · mid

  • A.等待所有worker到齐后统一更新参数
  • B.立即用这条梯度更新当前全局参数← 正确答案
  • C.先把梯度保存在内存中稍后批处理
  • D.将梯度原样返回给worker让其重算

答案:B。异步店规是“先到先改”,服务器收到就更新。A 是同步屏障;C 是延迟批处理,不是标准异步;D 毫无意义。抓住“收到即更新”就抓住了异步的精髓。

Q5. 以下哪些是缓解Stale Gradient的常用方法?

单选题 · mid

  • A.让过期程度越大的梯度权重越低← 正确答案
  • B.对梯度做裁剪以限制更新幅度← 正确答案
  • C.把每个worker的数据集扩大一倍
  • D.丢弃延迟超过阈值的过期更新← 正确答案

答案:ABD。延迟感知加权(A)、梯度裁剪(B)、阈值丢弃(D)是正文讲的三件套。扩大数据集(C)与缓解过期无关,反而增加单次计算时间。

Q6. 备份worker(backup worker)机制的核心思路是?

单选题 · mid

  • A.让每个worker各自维护两份参数副本
  • B.为慢worker提前准备替补来避免等待← 正确答案
  • C.在参数服务器外部再部署一台备用机
  • D.将训练数据复制多份发送给所有worker

答案:B。备份 worker 是总厨备好的“替班厨师”,某个分店太慢时直接让备份顶上,缓解同步屏障的等待损耗。A 是本地副本;C 是服务器冗余;D 是数据复制,均不符合。

Q7. 异步SGD中,梯度延迟τ的定义是?

单选题 · hard

  • A.梯度算完后网络传输所花费的时间
  • B.worker计算一个batch梯度所用的时长
  • C.参数版本在梯度计算期间被更新的次数← 正确答案
  • D.训练数据在整个数据集中的遍历次数

答案:C。τ 是“厨师抄菜谱”到“建议送达”之间,菜谱被改了多少版——是版本号的差,不是秒数。A、B 是时间单位,D 是 epoch,都与 staleness 的定义无关。

Q8. 关于异步SGD延迟对训练的影响,正确的有?

单选题 · hard

  • A.延迟越大梯度对当前参数的指导越弱← 正确答案
  • B.过大的延迟可能导致损失震荡不降← 正确答案
  • C.延迟只会影响收敛速度不会影响偏差
  • D.延迟可以用参数版本号之间的差衡量← 正确答案

答案:ABD。延迟越大,梯度描述的地形越旧,指导价值越低(A),严重时损失震荡(B),且版本号差就是 τ 的度量(D)。C 错误:过期梯度天然引入更新方向的偏差。

Q9. 为何说异步SGD的更新期望是“有偏”的?

单选题 · extreme

  • A.因为过期梯度的期望不等于真实梯度← 正确答案
  • B.因为学习率被设置得过大而导致的
  • C.因为梯度在传输中被量化压缩了精度
  • D.因为参数服务器存储参数时存在误差

答案:A。异步更新用 w_{t-τ} 处的梯度去更新 w_t,真实期望 E[g(w_{t-τ})] ≠ ∇L(w_t),这是结构性偏差,与学习率、量化、存储误差无关。有偏性是大规模异步训练在理论上必须正视的核心问题。

Q10. 以下哪些场景更适合异步SGD?

单选题 · mid

  • A.上千张卡且机器性能差异较大的集群← 正确答案
  • B.训练任务经常出现节点故障需要容错← 正确答案
  • C.小规模单机且对收敛过程极其敏感
  • D.在线学习有实时数据流不断到达更新← 正确答案

答案:ABD。大集群、异构、容错、实时数据流都是异步的舒适区。C 的单机小规模、强一致需求更适合同步模式,异步的吞吐优势无从发挥。