跳转至

Computing Systems Optimization

导言

我的长期职业目标可以收束为一句话:理解软件计算逻辑,把它映射到计算、通信、存储和容量受限的硬件上,通过拆分、掩盖、流水和协同设计提高有效利用率;再把这套理解变成可扩展的性能模型、硬件建议与团队分工。

这不是“会调几个 Kernel”或“熟悉某个训练框架”的目标。我要培养的是从工作负载、系统、软件到硬件的完整判断力:知道数据从哪里来、何时产生、在哪里停留、被谁消费、为什么等待,以及增加哪一种资源才真正缩短端到端关键路径。

目标不是一项技术

此前的 AI Technology Value Stack 回答了“为什么选择昂贵、可测、可复用的 AI 系统瓶颈”;AI Optimization Stack 回答了“模型、训练、推理、运行时、Kernel、通信与硬件分别控制什么”。本文进一步回答:我要把这些层培养成怎样的一项长期能力,以及怎样带领团队共同完成它。

表面目标是提高硬件利用率,更准确的目标却是:

在正确性、模型质量、服务 SLO、功耗、可靠性与成本约束下,提高端到端关键路径上的有效工作比例。

这一定义排除了三个危险捷径:

  • 忙不等于有效。 设备可以因为重试、冗余搬运、错误的 Batch、无效 Padding 或拥塞一直忙,但单位成本产出的有效结果反而更少。
  • 局部满不等于系统快。 一个 Kernel 达到高算力利用率,仍可能被排队、通信、Host 调度或流水空泡吞掉端到端收益。
  • 容量不是速率。 显存或内存容量决定任务能不能放下;带宽决定数据多久搬完。二者需要分别建模。

因此,我要长期拥有五种相互闭环的能力:

能力 要回答的问题 可验证产物
工作负载理解 软件真正计算什么,哪些语义不能改变? 计算图、状态图、输入输出契约
统一性能建模 计算、访存、通信、容量和空泡如何共同决定上限? 资源账本、时序模型、预测区间
优化实现 应拆分、重排、融合、掩盖还是改变并行策略? 代码、Microbenchmark、端到端 A/B
硬件反馈 哪个硬件短板的边际改善最值钱? 工作负载分布、敏感性与规格建议
技术组织 怎样让多人并行工作而不丢失系统最优? 模块合同、责任边界、集成验收

小黑测量四条资源管道并把瓶颈反馈给下一代硬件

概念插图:利用率优化不是把四条管道同时拧到最大,而是测出当前关键路径的窄口,验证调整后有效产出是否增加,再把稳定残差反馈给硬件设计。

优化的统一对象

四本账

可扩展的模型不应从某个 Profiler 指标开始,而应先维护四本相互连接的账:

  1. 逻辑账: 软件的节点、依赖、状态和不可改变的语义。它回答“先做什么、后做什么,哪些分支可以并行”。
  2. 资源账: 每个节点需要多少计算、设备内存流量、网络流量、内存/显存容量和工作空间。它回答“消耗了什么”。
  3. 时序账: 每个对象何时产生、最后一次被谁使用、何时释放;每个引擎何时工作、等待或争用。它回答“为什么出现空泡和峰值”。
  4. 证据账: 预测值、实测值、环境、误差与边界。它回答“这项判断在什么条件下成立”。

只有逻辑账,没有资源量,就只能画流程图;只有资源账,没有时序,就会把可重叠的时间机械相加;只有时序,没有对象生命周期,就解释不了显存峰值;没有证据账,模型再精细也只是故事。

资源—图—时序模型

我把这套可复用机制称为 资源—图—时序模型。概念层的目标是提高有效工作;机制层把工作负载变成图、资源需求和可执行时序;它不是某个框架补丁,每个项目仍需把模型实例化为真实的算子、Collective、Buffer、Stream、队列和硬件拓扑。

对象与公式

公式之前先固定核心对象,避免同一个“带宽”在规格、Microbenchmark 和实际任务之间偷换含义:

对象 生产者 单位或形态 消费者 生命周期与状态
工作负载图 \(G=(V,E)\) 语义与依赖分解 节点和有向边 调度器、模块 Owner 持久、版本化模型
节点需求 \(F_i,B_i^{mem},B_i^{net}\) 计算量、数据流与通信分析 operations、bytes 速率下界与资源账本 每组 Shape/精度/拓扑维护
活跃对象 \(M_j(t)\) 生产算子与状态机 随时间变化的 bytes 峰值容量模型与未来消费者 物理对象,最后消费后才可释放
可达上限 \(P_i^{att},BW_i^{att},NW_i^{att}\) 受控 Microbenchmark operations/s、bytes/s 节点下界 硬件、Shape、访问和拓扑参数
调度 \(S\) 依赖与资源约束求解 开始、结束、引擎、Buffer makespan 与生命周期 版本化实验产物
实测 \(Y\) 与残差 \(\epsilon\) Profiler 和端到端 Benchmark Trace、时间、bytes、计数器 模型校准 实测不可改,模型可更新

设工作负载图为 \(G=(V,E)\)。节点 \(v_i\) 表示一个计算或有状态阶段,边 \(e_{ij}\) 表示数据、控制或所有权依赖。对节点 \(i\) 记录:

  • \(F_i\):有效计算量,单位为 operations;
  • \(B_i^{mem}\):设备内存层级之间的有效流量,单位为 bytes;
  • \(B_i^{net}\):设备或节点之间的通信量,单位为 bytes;
  • \(M_j(t)\):对象 \(j\) 在时刻 \(t\) 仍存活的容量,单位为 bytes。

再用同一 Shape、数据类型、访问模式和拓扑下的可达上限 \(P_i^{att}\)\(BW_i^{att}\)\(NW_i^{att}\) 计算一个速率下界:

\[ T_i^{roof} \ge \max \left( \frac{F_i}{P_i^{att}}, \frac{B_i^{mem}}{BW_i^{att}}, \frac{B_i^{net}}{NW_i^{att}} \right) \]

这个式子只回答“最快不能低于多少”,不直接预测真实耗时。真实节点时间 \(T_i\) 还要加入启动、同步、Shape 尾部、资源占用、协议和运行时校准;系统时间也不是 \(\sum_i T_i\),而是依赖图与资源约束下的 makespan,即最后一个必要输出完成的时间。

容量则是另一条约束:

\[ M_{peak} = \max_t \left( \sum_{j \in live(t)} M_j(t) + M_{workspace}(t) + M_{allocator}(t) + M_{margin}(t) \right) \]

其中 live(t) 是时刻 \(t\) 仍会被未来计算消费的对象集合。一个对象大小不变,只要提前结束生命周期,也可能降低峰值;反过来,逻辑上已经“不再使用”的 View 仍引用底层 Storage 时,显存并不会释放。

在一个测量窗口内,资源 \(r\) 的有效利用率可写成:

\[ U_r = \frac{D_r^{useful}} {C_r^{att} \cdot T_{window}} \]

\(D_r^{useful}\) 是产生最终有效结果所必需的需求,\(C_r^{att}\)实际分配给该工作负载的可达能力,而不是整机规格表峰值。对稳态流水,Little 的排队关系给出 \(L=\lambda W\):平均在途任务数 \(L\) 等于吞吐 \(\lambda\) 乘平均停留时间 \(W\)。它可以检查并发量是否足以填满流水,但只有在长期平均有限、系统近似稳定时才适用。3

完整伪代码

完整的教学伪代码如下。它不隐藏分解、计量、调度、校准和回写步骤:

def analyze_system(workload, hardware, baseline_measurement):
    graph = build_dependency_graph(workload.semantic_steps)
    validate_semantic_equivalence(graph, workload.correctness_contract)

    node_models = {}
    live_intervals = []

    for node in topological_order(graph):
        compute_ops = count_useful_operations(node)
        memory_bytes = count_device_memory_traffic(node)
        network_bytes = count_network_traffic(node, hardware.topology)
        object_intervals = trace_object_lifetimes(node)

        attainable_compute = microbenchmark_compute(
            hardware, node.shape, node.dtype, node.instruction_mix
        )
        attainable_memory = microbenchmark_memory(
            hardware, node.shape, node.access_pattern
        )
        attainable_network = microbenchmark_network(
            hardware.topology, node.message_sizes, node.collective
        )

        rate_floor = max(
            compute_ops / attainable_compute,
            memory_bytes / attainable_memory,
            network_bytes / attainable_network,
        )
        calibrated_duration = calibrate_node_duration(
            rate_floor,
            node.launch_count,
            node.synchronization_points,
            node.tail_shape,
            baseline_measurement,
        )

        node_models[node.id] = {
            "duration": calibrated_duration,
            "compute_ops": compute_ops,
            "memory_bytes": memory_bytes,
            "network_bytes": network_bytes,
        }
        live_intervals.extend(object_intervals)

    schedule = place_nodes_with_dependencies_and_resource_limits(
        graph, node_models, hardware.engines, hardware.capacity
    )
    predicted_makespan = finish_time_of_required_output(schedule)
    predicted_peak_memory = maximum_live_bytes(
        live_intervals, schedule, hardware.allocator_margin
    )

    residual = compare_prediction_with_measurement(
        predicted_makespan,
        predicted_peak_memory,
        baseline_measurement,
    )
    residual_causes = classify_residual(
        residual,
        graph,
        schedule,
        baseline_measurement.trace,
        baseline_measurement.hardware_state,
    )
    updated_model = update_only_supported_assumptions(
        node_models, residual_causes
    )

    return updated_model, schedule, residual_causes

对象完整性审计的标准是:图上每个节点和边都能回到输入、输出或状态;公式中的每个 demand 都有计量方法;每个物理对象都有生产者、最后消费者与释放时刻;每个可达上限都带 Shape、精度、拓扑和环境。没有来源的对象不能靠一个“其他开销”长期隐藏。

五视图与边界

资源—图—时序统一模型五视图

本文自绘五视图:A 看拆分前后的物理空泡,B 看瓶颈到代价的因果链,C 看完整建模流程,D 看计算、HBM 与网络对象的生命周期,E 看输入、模块、边和输出的数据量。它表达可复用机制,不对应某一框架补丁。

读这张图时,不能只看一条箭头:A 面板验证是否真的减少空闲;B 面板保留“新代价”;C 面板要求实测残差回写;D 面板检查等待与释放位置;E 面板确保每个资源数字都有数据对象来源。

效果契约

这套模型直接针对的是调度空泡、错误资源归因和不可解释的容量峰值。它不会自动带来性能收益;新增成本包括计量、Profiler、Microbenchmark、模型维护和跨模块同步。只有同语义端到端 A/B 证明 makespan、成本或 SLO 改善后,才能报告数值收益。

适用边界

这套方法要求工作负载语义可固定、关键对象可观测、硬件环境可记录。对强非平稳在线流量,应建模分布、分位数和状态转移,不能只用长期平均;对不可观测的固件或闭源运行时,只能给残差区间和反事实实验,不能伪造内部因果链。

模型如何逐层收敛

全局先看关键路径

全局模型关注的不是每个模块有多快,而是总资源如何分配、哪个依赖链决定完成时间、哪些设备在何时出现空泡。至少要同时保留:

  • 依赖关键路径: 不能通过增加并行度消除的前后关系;
  • 资源关键路径: 逻辑可并行,但争用同一计算单元、HBM、网络或 Host 线程;
  • 容量关键路径: 某组对象必须同时存活,迫使 Chunk、Offload 或重计算;
  • 队列关键路径: 请求到达、Batch 形成、抢占和长尾 Shape 造成的等待;
  • 功耗关键路径: 计算、HBM 与互连并发后触发功耗墙或降频。

这一步的产物应是一张全局时序图和资源热力图。若端到端时间由通信后的 Barrier 决定,把非关键分支上的 Kernel 再优化 20% 也不会产生相同比例收益。Amdahl 早已指出,序列或 housekeeping 部分会限制并行加速;现代系统只是把“序列部分”扩展成同步、调度、数据准备与尾部等待。2

模块再看对象流

每个模块都要回答一个相同的问题模板:

视图 必答问题
计算流程图 做了哪些 Projection、MatMul、Reduce、Collective 或状态更新?
时序图 输入到达多久后开始,多久后产生第一批与全部输出?
逻辑图 哪些依赖必须保留,哪些分支可以拆开或重排?
数据量图 输入、输出、中间对象、网络消息与工作空间各有多少 bytes?
资源上限 计算、访存、通信和容量中的哪一项先触顶?
验收图 Microbenchmark 改变了哪个物理量,端到端是否进入关键路径?

模块模型不是一次性 Excel。它应以 Shape、数据类型、并行拓扑、Batch/序列分布和硬件版本为参数;每次实测都留下预测、残差与解释。模型能迁移到第二个模块或第二种硬件,才开始形成长期竞争力。

上限差距不能消失

“建模估算与实际的差距”至少要拆成四类:

  1. 对象误差: 少算了一个 Buffer、重计算、Layout 转换、Host 同步或通信协议。
  2. 上限误差: 把规格峰值当成了特定 Shape、精度、访问模式和拓扑下的可达上限。
  3. 调度误差: 假设可以重叠,实际存在依赖、引擎冲突、Buffer 复用、Barrier 或尾部不均衡。
  4. 环境误差: 频率、功耗、温度、ECC、NUMA、网络拥塞、后台任务和版本变化。

因此,差距不能被彻底“避免”,但可以用五级上限梯子缩小并定位:

层级 上限来源 回答的问题
规格峰值 手册中的 FLOPS、带宽、容量 物理设计宣称什么?
可达上限 同 Shape/精度/访问/拓扑的 Microbenchmark 当前环境最多能交付什么?
Kernel/Collective 实测 单个实现的 Profiler 实现离可达上限多远?
模块实测 含调用、转换、同步与工作空间 集成开销是多少?
端到端实测 真实请求/训练步/任务 是否进入关键路径并改善主指标?

Roofline 论文的核心价值不是精确预测,而是用上界和瓶颈指导下一步。Figure 1 把计算峰值与可持续内存带宽共同画成上界;右图也显示,计算峰值提高而内存带宽不变时,转折点会右移,更多程序可能仍受内存限制。1

Roofline 论文 Figure 1

来自 Roofline 论文 Figure 1。它证明如何用计算峰值与可持续内存带宽形成上界;不证明现代 GPU/NPU 集群的端到端性能可以由这两条线完整预测。

论文 Table 4 更重要的证据是:不同 Kernel 在不同机器上靠近的上限并不相同。例如表中 Intel Xeon 的 SpMV 达到 11.1 GB/s,而相邻上限是 11.2 GB/s;IBM Cell 的 SpMV 达到 47.1 GB/s,而相邻上限是 47.6 GB/s。其他行则暴露 FMA、SIMD、Affinity 或 TLP 等更低一层天花板。1

Roofline 论文 Table 4

来自 Roofline 论文 Table 4。它支持“用最近天花板定位优化方向”,但实验只覆盖论文中的四类 Kernel 与四种 2009 年前后的多核系统,不能外推为现代 AI 系统的统一误差保证。

实务中应把每级差距写成残差:

端到端残差
    = 对象遗漏
    + 可达上限校准
    + 调度与生命周期
    + 运行时与环境
    + 测量噪声

每次只在证据支持时增加模型细节。若新增参数不能改变瓶颈判断、预测区间或设计决策,它只是复杂度,不是理解力。

拆分、掩盖与流水

拆分、掩盖和流水不是三个口号,而是对同一时序图的三种物理动作:

动作 改变什么 直接收益 新代价与失败条件
拆分 把大对象或长任务切成可调度 Chunk 降低局部峰值、增加并行机会、改善尾部 更多启动、边界处理、通信与碎片;Chunk 太小会反向变慢
掩盖 让相互独立的计算、通信或搬运同时发生 从关键路径隐藏部分等待 需要独立引擎、依赖自由、双 Buffer 和足够在途工作;资源争用会让两边都变慢
流水 让不同阶段处理不同批次或 Micro-batch 填补阶段空闲,提高稳态吞吐 启停气泡、阶段不均衡、状态数量、尾部与同步仍然存在

CUDA 的异步接口允许 Host、Device、内存传输和设备间操作表达并发,但官方文档也明确指出,实际并发取决于硬件能力,并需要在结果被消费前同步。7 因此,“调用是 async”只能证明提交方式,不能证明 makespan 已经缩短。

一个优化动作只有同时满足下面四个条件才算成立:

  1. 语义可拆: 依赖、数值和状态允许切分或重排;
  2. 资源可并: 两条路径没有争用同一个瓶颈引擎、容量或功耗预算;
  3. 对象可活: Buffer 的生产、消费、复用和释放时机正确;
  4. 证据可见: Trace 中的空泡缩小,端到端指标在同条件 A/B 中改善。

让模型反向设计硬件

感知硬件短板不是看到某个计数器 100%,而是回答一个反事实问题:

如果只增加这一项资源,保持软件语义、其他硬件能力和成本约束不变,端到端目标能改善多少?

可以对可达计算、HBM 带宽、互连带宽、片上容量、显存容量、DMA 并发或特定指令做局部敏感性实验:

\[ S_r = -\frac{\Delta T_{end}}{\Delta C_r} \]

\(S_r\) 表示资源 \(r\) 的边际时间价值。实际硬件优先级还要除以面积、功耗、成本和实现风险,并在工作负载分布上求期望,而不是只看一个模型的最好 Case:

硬件优先级
    ~ 工作负载覆盖率
    × 端到端敏感性
    × 软件可达性
    × 证据置信度
    ÷ 面积、功耗、成本与实现风险

这里的 \(S_r\) 应通过多个受控容量点做有限差分和置信区间,而不是把一次模拟结果当作全局线性导数。瓶颈移动后,继续增加同一资源的边际价值通常会下降。

这里的“软件可达性”非常关键。若编译器、运行时、指令、内存一致性或通信接口无法稳定表达目标数据流,再高的硬件峰值也不会被应用使用。Hennessy 与 Patterson 把软件推动架构创新、提升软硬件接口视为新架构机会;这支持双向反馈,却不保证任何定制单元都会商业成功。6

面向硬件团队的建议不应写成“需要更大带宽”,而应包含:

  • 代表性工作负载、Shape 与时间分布;
  • 当前关键路径和可复现基线;
  • 资源增加前后的模拟或原型结果;
  • 软件、编译器和运行时所需接口;
  • 面积、功耗、容量、可靠性和成本边界;
  • 哪些 Case 获益,哪些 Case 不变或退化。

把系统切成团队

模块边界

团队分工不能先画组织架构,再强迫软件服从。应先从软件图和资源图选择模块边界:

  1. 状态所有权清楚: 哪个模块创建、更新、持有和释放对象?
  2. 接口相对稳定: 输入输出与语义稳定,内部实现可以独立变化。
  3. 验证可以闭环: 模块能独立做正确性、性能和边界测试。
  4. 资源冲突可描述: 计算、通信、容量和功耗争用能在接口上暴露。
  5. 并行工作真实存在: 两个团队不必频繁修改同一状态机或等待同一决策。

Parnas 的模块化原则不是按处理步骤机械切函数,而是把可能变化的设计决策隐藏在模块内部,以降低变化传播。4 对性能团队,还要再加一条:把需要联合优化的资源冲突暴露成共同合同,而不是藏进某一方的实现细节。

每个模块至少维护四类合同:

合同 内容 失败示例
功能合同 输入、输出、状态、正确性与精度 两边对 Padding、顺序或状态语义理解不同
资源合同 FLOPs、bytes、容量、工作空间、并发引擎 局部优化偷偷增加全局峰值
时序合同 何时 ready、何时完成、同步与释放 async 接口返回被误当作数据可用
证据合同 基线、环境、指标、回归与回滚 只给最好一次数字,无法集成复现

责任结构

我希望管理的不是一群孤立专家,而是一套共享模型下的模块所有者:

角色 主要责任 不应独占的权力
系统性能负责人 定义端到端目标、全局模型、关键路径和模块合同 不能替模块所有者写完所有详细实现
计算模块负责人 算子、编译、Tile、融合和计算上限 不能忽略数据搬运与端到端占比
通信模块负责人 Collective、P2P、拓扑、协议与 Overlap 不能只报告链路带宽
内存与运行时负责人 对象生命周期、Allocator、队列、调度和 Host 路径 不能把容量问题等同于带宽问题
测量与集成负责人 Trace、基线、回归、环境控制与跨模块验收 不能成为事后测试员
硬件协同接口人 聚合工作负载、敏感性和规格建议 不能从单个热点直接承诺硬件收益

Conway 在 1968 年指出,组织结构会限制可有效探索的设计方案;任务一旦委派,也会立即产生协调问题。5 因此,团队边界必须跟随系统概念迭代。若新的 Trace 证明两个模块长期共同决定同一关键路径,就应建立联合 Owner、共同基线或重新切分,而不是坚持最初组织图。

技术管理

这也澄清了我对“管理”的真实目标:我未必想把主要精力放在人员行政、情绪协调和汇报层级上,但我需要具备技术组织能力

技术管理不是离开技术,而是:

  • 用统一对象和指标消除口径冲突;
  • 让全局模型决定优先级,而不是职位或声音大小;
  • 给模块 Owner 足够的设计空间,同时守住接口与证据;
  • 在局部最优伤害系统最优时及时止损;
  • 培养第二层负责人,使模型、实现和判断不依赖一个人。

团队每个迭代按同一个闭环运行:

  1. 系统负责人冻结口径: 发布当前 Baseline、前三个关键瓶颈、不可改变的语义和端到端验收。
  2. 模块 Owner 提交反事实: 说明改哪个对象、预期改变哪条资源或生命周期、会新增什么代价。
  3. 接口双方共同评审: 对跨模块 Buffer、完成事件、Shape 与回滚条件建立共同 Owner,不能把风险推到边界外。
  4. 测量与集成统一验收: 先验局部物理量,再验端到端关键路径;失败结果同样进入证据账。
  5. 复盘后重画系统: 更新残差、优先级与模块边界;瓶颈移动时及时停止旧方向。

最终,一名系统负责人不需要掌握每个模块的全部代码,却必须能审查每个模块的对象、数据量、时序、上限、残差与集成影响。团队规模扩展的本质,是让判断模型扩展,而不是让会议数量扩展。

培养路线

这条职业路线可以按责任半径逐步扩大:

阶段 核心任务 必须留下的资产 晋级证据
单模块 对一个算子、Collective 或运行时路径建立完整模型 对象账本、Microbenchmark、Profiler、边界测试 预测能解释主要残差,局部收益可复现
端到端链路 把多个模块放入同一关键路径与容量模型 全局时序、峰值账本、同语义 A/B 能拒绝无端到端价值的局部优化
跨硬件迁移 在 GPU/NPU 或两代硬件上校准同一模型 可达上限梯子、迁移规则、失败 Case 能区分通用机制与硬件补丁
软硬协同 用敏感性与原型提出硬件/接口改进 工作负载集、反事实结果、规格合同 建议能覆盖一类负载而非单点热点
团队负责人 让多个 Owner 在共享模型下并行交付 模块合同、集成节奏、培养与复盘机制 团队离开个人微观指挥仍能稳定闭环

每个项目结束时,至少沉淀五件东西:

  1. 工作负载图: 语义、Shape、状态和依赖;
  2. 资源账本: 计算、访存、通信、容量和功耗;
  3. 时序与生命周期: 关键路径、空泡、峰值和释放;
  4. 证据包: Baseline、A/B、Trace、环境与残差;
  5. 复用模块: 代码、工具、模型、接口、测试或硬件建议。

失败标准

下面几种状态说明路线正在偏离:

  • 只追计数器: 指标漂亮,但单位成本、端到端时间、质量或 SLO 没有改善。
  • 只做局部补丁: 每个新模型都重新适配,无法沉淀第二个 Case 可复用的对象和接口。
  • 模型无限变复杂: 参数越来越多,却不能改变瓶颈判断、预测区间或优先级。
  • 按组织切软件: 团队边界遮蔽真实依赖,接口处长期出现返工和无人负责的性能损失。
  • 从热点跳到硬件: 没有反事实敏感性、覆盖率和面积功耗成本,就提出下一代规格。
  • 负责人亲自承包一切: 局部质量依赖一个人,模块 Owner 没有模型与验收责任,团队无法扩展。

最危险的成功

最危险的不是一次优化失败,而是某个局部数字成功后被错误推广:Kernel 快了、通信带宽高了、显存降了,但系统瓶颈已经移动,甚至总成本变差。每次成功都必须重新建模,而不是永久贴上“已优化”标签。

总结

我的长期职业目标不是绑定某个模型、框架、芯片或岗位名称,而是建立一项可迁移的系统能力:

从软件逻辑出发,把计算、访存、通信、容量、调度和功耗放进同一资源—图—时序模型;通过拆分、掩盖与流水提高关键路径上的有效硬件利用率;用实测残差收敛模型,用反事实敏感性指导下一代硬件,再把模型转化为可并行、可验收、可培养的团队责任。

这条路线的核心竞争力不是“知道答案”,而是能把复杂系统变成可解释对象,把估算误差变成下一步调查,把局部优化变成端到端证据,把个人理解变成团队共同使用的模型。

参考资料


  1. Samuel Williams, Andrew Waterman, David Patterson, Roofline: An Insightful Visual Performance Model for Multicore Architectures, Communications of the ACM 52(4), 2009. 本文图表取自 OSTI 公开 PDF。 

  2. Gene M. Amdahl, Validity of the Single Processor Approach to Achieving Large Scale Computing Capabilities, AFIPS Spring Joint Computer Conference, 1967. 

  3. John D. C. Little, A Proof for the Queuing Formula: L = λW, Operations Research 9(3), 1961. 

  4. David L. Parnas, On the Criteria To Be Used in Decomposing Systems into Modules, Communications of the ACM 15(12), 1972. 

  5. Melvin E. Conway, How Do Committees Invent?, Datamation, April 1968. 

  6. John L. Hennessy, David A. Patterson, A New Golden Age for Computer Architecture, Communications of the ACM 62(2), 2019. 

  7. NVIDIA, CUDA Programming Guide: Asynchronous Execution and Asynchronous Data Copies, accessed 2026-07-31. 

评论