C++高性能并行编程与优化 - 课件 - 07 深入浅出访存优化
)。 • 并行能减轻计算瓶颈,但不减轻内存瓶颈,故后者是优化的重点 。 浮点加法的计算量 • 冷知识:并行地给浮点数组每个元素做一次加法反而更慢。 • 因为一次浮点加法的计算量和访存的超高延迟相比实在太少了。 • 计算太简单,数据量又大,并行只带来了多线程调度的额外开销 。 • 小彭老师经验公式: 1 次浮点读写 ≈ 8 次浮点加法 • 如果矢量化成功( SSE ): 1 次浮点读写 cycle , 符合小彭老师的经验公式。 • “right” 和“ wrong” 指的是分支预测是否成功。 多少计算量才算多? • 看右边的 func ,够复杂了吧?也只是勉勉强强超过一 点内存的延迟了,但在 6 个物理核心上并行加速后, 还是变成 mem-bound 了。 • 加速比: 1.36 倍 • 应该达到 6 倍(物理核心数量)才算理想加速比。 加速曲线 • funcA 用了 可见数据量较小时,实际带宽甚至超过了 理论带宽极限 42672 MB/s ! • 而数据量足够大时, 才回落到正常的带宽 。 • 这是为什么? CPU 内部的高速缓存 • 原来 CPU 的厂商早就意识到了内存延迟高,读写效率低 下的问题。因此他们在 CPU 内部引入了一片极小的存储 器——虽然小,但是读写速度却特别快。这片小而快的 存储器称为缓存( cache )。 • 当 CPU 访问某个地址时,会先查找缓存中是否有对应的0 码力 | 147 页 | 18.88 MB | 1 年前3Rust分布式账务系统 - 胡宇
Airwallex 从设计架构到实现细节 项目介绍 分布式账务系统 Fintech 互联网 正确性 bug= 资损 bug 不可怕,快速迭代 可靠性 丢数据 = 资损 允许数据丢失 性能 超低延迟 + 高吞吐 超高吞吐 交易日志 审计,监管 调试使用 分布式账务系统 Fintech 领域中的软件与互联网软件的不同 需求分析 支付处理: ● 转账 ● 冻资 / 解资 ● 账户限额 批处理事务 正确性:无双花或少付 审计监管:交易日志不可篡改,交易历史可回溯 条件事务:根据一定的条件决定事务执行与否 高可用:在部分节点失效的情况下,依旧可以提供正确的 服务 超低延迟:实时交易,超低响应延迟 水平扩展性:利用分布式事务实现钱包集群的的水平扩 展,应对高达 100 万 TPS 的流量 可演化性:业务逻辑与底层 API 解耦,当业务发生改变 时,底层 API 不用改变 分布式账务系统 id 进行分区 ○ 执行账户变动请求 ○ 更新账户余额 分布式账务系统 性能展示 8 vCPUs * 5 节点 SSD 磁盘 当 TPS = 10K 时, 延迟 P99 < 20ms 分布式账务系统 高吞吐,超低延迟 账户层: Auticuro 分布式账务系统 账户层: Auticuro ● 1. 接受转账请求,转换成 events ○ Tokio + Tonic 分布式账务系统0 码力 | 27 页 | 12.60 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程
板块中的线程数量过少:延迟隐藏( latency hiding )失效 • 我们说过,每个 SM 一次只能执行板块中的一个线程组( warp ),也就是 32 个线程。 • 而当线程组陷入内存等待时,可以切换到另一个线程,继续计算,这样一个 warp 的内存 延迟就被另一个 warp 的计算延迟给隐藏起来了。因此,如果线程数量太少的话,就无法 通过在多个 warp 之间调度来隐藏内存等待的延迟,从而低效。 共享内存区块冲突( bank conflict ) GPU 优化手法总结 • 线程组分歧( wrap divergence ):尽量保证 32 个线程都进同样的分支,否则两个分支都会执行 。 • 延迟隐藏( latency hiding ):需要有足够的 blockDim 供 SM 在陷入内存等待时调度到其他线程 组。 • 寄存器打翻( register spill ):如果核函数用到很多局部变量(寄存器),则0 码力 | 142 页 | 13.52 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 03 现代 C++ 进阶:模板元编程
列出所有模板参数的排列组合 ,违背了开 - 闭原则。 模板的惰性:延迟编译 • 要证明模板的惰性,只需看这个例子: • 要是编译器哪怕细看了一眼:字符串怎么可能被写入呢?肯定是会出错的。 • 但是却没有出错,这是因为模板没有被调用,所以不会被实际编译! • 而只有当 main 调用了这个函数,才会被编译,才会报错! • 用一个假模板实现延迟编译的技术,可以加快编译的速度,用于代理模式等。 模板函数:一个例子0 码力 | 82 页 | 12.15 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 10 从稀疏数据结构到量化数据类型
)。 • 右边就是一个很好的例子。 使用 int64_t :每个占据 8 字节 • 如果用更大的数据类型,用时会直接提升两倍! • 这是因为 i % 2 的计算时间,完全隐藏在内存 的超高延迟里了。 • 可见,当数据量足够大,计算量却不多时,读写 数据量的大小唯一决定着你的性能。 • 特别是并行以后,计算量可以被并行加速,而访 存却不行。 使用 int8_t :每个占据 1 字节0 码力 | 102 页 | 9.50 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅
域按照常规的两层循环访问以便矢量化,块外 部大区域则以类似 Z 字型的曲线遍历,这样 能保证每次访问的数据在地址上比较靠近,并 且都是最近访问过的,从而已经在缓存里可以 直接读写,避免了从主内存读写的超高延迟。 • 下次课会进一步深入探讨访存优化,详细剖析 这个案例,那么下周六 14 点敬请期待。 第 6 章:并发容器 std::vector 扩容时会移动元素 • std::vector 内部存储了一个指针,指向一段容量0 码力 | 116 页 | 15.85 MB | 1 年前3
共 6 条
- 1