 C++高性能并行编程与优化 -  课件 - 14 C++ 标准库系列课 - 你所不知道的 set 容器pos); 1 2 3 4 5 find(4) begin() prev(end()) end() set 增删改查操作总结 操作 实现方法 增 a.insert(x) 删 a.erase(x) 或者 a.erase(a.find(x)) 改 一旦插入就无法修改,只能先删再增 查 a.find(x) != a.end() 或者 a.count(x) 从 set 中删除指定范围的元素 • ForwardIt end); set 的妙用:排序 • 刚刚说,把 vector 转成 set 会让元素自动排序和去 重。 • 我们其实可以利用这一点,把 vector 转成 set 再转 回 vector ,这样就实现去重了。 • template C++高性能并行编程与优化 -  课件 - 14 C++ 标准库系列课 - 你所不知道的 set 容器pos); 1 2 3 4 5 find(4) begin() prev(end()) end() set 增删改查操作总结 操作 实现方法 增 a.insert(x) 删 a.erase(x) 或者 a.erase(a.find(x)) 改 一旦插入就无法修改,只能先删再增 查 a.find(x) != a.end() 或者 a.count(x) 从 set 中删除指定范围的元素 • ForwardIt end); set 的妙用:排序 • 刚刚说,把 vector 转成 set 会让元素自动排序和去 重。 • 我们其实可以利用这一点,把 vector 转成 set 再转 回 vector ,这样就实现去重了。 • template- • void assign(ForwardIt beg, ForwardIt end); 清空 set 会返回第一个等于 x 的元素的迭代器。找不到也 是返回 end() 。 multiset 增删改查操作总结 操作 实现方法 增 a.insert(x) 删 a.erase(x) 或者 a.erase(a.lower_bound(x), a.upper_bound(x)) 改 一旦插入就无法修改,只能先删再增 查 a.find(x) != a.end() 或者 a.count(x) set 系列成员函数总结 0 码力 | 83 页 | 10.23 MB | 1 年前3
 C++高性能并行编程与优化 -  课件 - 02 现代 C++ 入门:RAII 内存管理编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 cpu 缓存机制 8.GPU 专题: wrap 调度,共享内存, barrier 9.并行算法实战: reduce , scan ,矩阵乘法等 10.存储大规模三维数据的关键:稀疏数据结构 11.物理仿真实战:邻居搜索表实现 管理的对象生命周期长度,取决于他所属的唯一一个引用的寿命 。 那是不是只要 shared_ptr 就行,不用 unique_ptr 了? • 可以适当使用减轻初学者的压力,因为他的行为和 Python 等 GC 语言的引用计数机制很像。但从长远 来看是不行的,因为: 1. shared_ptr 需要维护一个 atomic 的引用计数器, 效率低,需要额外的一块管理内存,访问实际对象 需要二级指针,而且 deleter 因为他们的业务需求大多是:打开数据库,增删改查学生数据,打开一个窗口,写入一个 文件,正则匹配是不是电邮地址,应答 HTTP 请求等。 • 这些业务往往都是在和资源打交道,从而基本都是刚刚说的要删除拷贝函数的那一类,解 决这种需求,几乎总是在用 shared_ptr C++高性能并行编程与优化 -  课件 - 02 现代 C++ 入门:RAII 内存管理编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 cpu 缓存机制 8.GPU 专题: wrap 调度,共享内存, barrier 9.并行算法实战: reduce , scan ,矩阵乘法等 10.存储大规模三维数据的关键:稀疏数据结构 11.物理仿真实战:邻居搜索表实现 管理的对象生命周期长度,取决于他所属的唯一一个引用的寿命 。 那是不是只要 shared_ptr 就行,不用 unique_ptr 了? • 可以适当使用减轻初学者的压力,因为他的行为和 Python 等 GC 语言的引用计数机制很像。但从长远 来看是不行的,因为: 1. shared_ptr 需要维护一个 atomic 的引用计数器, 效率低,需要额外的一块管理内存,访问实际对象 需要二级指针,而且 deleter 因为他们的业务需求大多是:打开数据库,增删改查学生数据,打开一个窗口,写入一个 文件,正则匹配是不是电邮地址,应答 HTTP 请求等。 • 这些业务往往都是在和资源打交道,从而基本都是刚刚说的要删除拷贝函数的那一类,解 决这种需求,几乎总是在用 shared_ptr- 的模式,于是 Java 和 Python 干 脆简化:一切非基础类型的对象都是浅拷贝,引用计数由垃圾回收机制自动管理。 • 因此 0 码力 | 96 页 | 16.28 MB | 1 年前3
 Zadig 面向开发者的云原生 DevOps 平台来和云端做交互,利用 Zadig 能力完成车端和云端服务的迭代更新 过程: 主机方式接入资源设备 • 支持系统主机管理的同时支持了项目级别的主机管理,项目成员可 以自己上下线资源设备 • 主机管理支持强大的探活机制 (TCP/HTTP 协议 ) ,精准检测资源设 备是否在线。 • 服务可以查看到关联的主机资源,支持登录主机,方便开发登录资 源设备诊断问题 • 完备的权限控制,极大降低了管理成本,实现安全风险可控。 扫 码 查 看 案 例 细 节 典型案例: Zadig 帮助 平均每周自动部署 1200 次 Zadig 可用性极高,没有 Zadig 集成测试完 全没法做。 —— 字节跳动 SRE 工程师卢肇 兴 解决方案: Gerrit + Zadig 实现机器自动验证 扫 码 查 看 案 例0 码力 | 59 页 | 81.43 MB | 1 年前3 Zadig 面向开发者的云原生 DevOps 平台来和云端做交互,利用 Zadig 能力完成车端和云端服务的迭代更新 过程: 主机方式接入资源设备 • 支持系统主机管理的同时支持了项目级别的主机管理,项目成员可 以自己上下线资源设备 • 主机管理支持强大的探活机制 (TCP/HTTP 协议 ) ,精准检测资源设 备是否在线。 • 服务可以查看到关联的主机资源,支持登录主机,方便开发登录资 源设备诊断问题 • 完备的权限控制,极大降低了管理成本,实现安全风险可控。 扫 码 查 看 案 例 细 节 典型案例: Zadig 帮助 平均每周自动部署 1200 次 Zadig 可用性极高,没有 Zadig 集成测试完 全没法做。 —— 字节跳动 SRE 工程师卢肇 兴 解决方案: Gerrit + Zadig 实现机器自动验证 扫 码 查 看 案 例0 码力 | 59 页 | 81.43 MB | 1 年前3
 C++高性能并行编程与优化 -  课件 - 07 深入浅出访存优化缓存的工作机制:读 • 缓存中存储的数据结构: • struct CacheEntry { • bool valid; • uint64_t address; • char data[64]; • }; • CacheEntry cache[512]; • 当 CPU 读取一个地址时: • 缓存会查找和该地址匹配的条目。如果找到,则给 CPU 返 回缓存中的数 个字节时,实际会导致 0x0040~0x0080 的 64 字节数据整个被读取到缓存中。 • 这就是为什么我们喜欢把数据结构的起始地址和大小对齐到 64 字节,为的是不要浪费缓存行的存储空间。 缓存的工作机制:写 • 缓存中存储的数据结构: • struct CacheEntry { • bool valid, dirty; • uint64_t address; • char )才能最高效,原因稍后会说明。 AOSOA :注意,内部 SOA 的尺寸不宜太小 如果内部 SOA 太小,内部循环只有 16 次连续的读 取, 16 次结束后就会跳跃一段,然后继续连续的 读取。这会导致 CPU 预取机制失效,无法预测下 一次要读哪里,等发现跳跃时已经来不及了,从而 计算的延迟无法隐藏。 如果每个属性都要访问到,那还是 AOS 比较好( AOSOA 也不赖哦) 这是因为使用 SOA 会让 CPU0 码力 | 147 页 | 18.88 MB | 1 年前3 C++高性能并行编程与优化 -  课件 - 07 深入浅出访存优化缓存的工作机制:读 • 缓存中存储的数据结构: • struct CacheEntry { • bool valid; • uint64_t address; • char data[64]; • }; • CacheEntry cache[512]; • 当 CPU 读取一个地址时: • 缓存会查找和该地址匹配的条目。如果找到,则给 CPU 返 回缓存中的数 个字节时,实际会导致 0x0040~0x0080 的 64 字节数据整个被读取到缓存中。 • 这就是为什么我们喜欢把数据结构的起始地址和大小对齐到 64 字节,为的是不要浪费缓存行的存储空间。 缓存的工作机制:写 • 缓存中存储的数据结构: • struct CacheEntry { • bool valid, dirty; • uint64_t address; • char )才能最高效,原因稍后会说明。 AOSOA :注意,内部 SOA 的尺寸不宜太小 如果内部 SOA 太小,内部循环只有 16 次连续的读 取, 16 次结束后就会跳跃一段,然后继续连续的 读取。这会导致 CPU 预取机制失效,无法预测下 一次要读哪里,等发现跳跃时已经来不及了,从而 计算的延迟无法隐藏。 如果每个属性都要访问到,那还是 AOS 比较好( AOSOA 也不赖哦) 这是因为使用 SOA 会让 CPU0 码力 | 147 页 | 18.88 MB | 1 年前3
 C++高性能并行编程与优化 -  课件 - 08 CUDA 开启的 GPU 编程ious-nvidia-cards/ 更老的版本如 GT-630 已经被 CUDA 11 废除,因此本课程要 求同学有 GTX900 及以上显卡。如果需要在老显卡上运行的话 ,可以看下面那个链接,查一下你的显卡对应的版本号是多少 ,然后在 CMake 里设置个一样的,应该就能用了。 小彭老师每日锐评 • 顺便, Pascal 、 Turing 、 Ampere 什么的高大上架构名,那个是老黄拿来营销用的。 里的板块数和线程数可以动态指定,无需 先传回到 CPU 再进行调用,这是 CUDA 特有的能力。 常用于这种情况:需要从 GPU 端动态计算出 blockDim 和 gridDim ,而又不希望导回数据到 CPU 导致强制同步影响性能。 这种模式被称为动态并行( dynamic parallelism ), OpenGL 有一 个 glDispatchComputeIndirect 的 API 和这个很像,但毕竟没有0 码力 | 142 页 | 13.52 MB | 1 年前3 C++高性能并行编程与优化 -  课件 - 08 CUDA 开启的 GPU 编程ious-nvidia-cards/ 更老的版本如 GT-630 已经被 CUDA 11 废除,因此本课程要 求同学有 GTX900 及以上显卡。如果需要在老显卡上运行的话 ,可以看下面那个链接,查一下你的显卡对应的版本号是多少 ,然后在 CMake 里设置个一样的,应该就能用了。 小彭老师每日锐评 • 顺便, Pascal 、 Turing 、 Ampere 什么的高大上架构名,那个是老黄拿来营销用的。 里的板块数和线程数可以动态指定,无需 先传回到 CPU 再进行调用,这是 CUDA 特有的能力。 常用于这种情况:需要从 GPU 端动态计算出 blockDim 和 gridDim ,而又不希望导回数据到 CPU 导致强制同步影响性能。 这种模式被称为动态并行( dynamic parallelism ), OpenGL 有一 个 glDispatchComputeIndirect 的 API 和这个很像,但毕竟没有0 码力 | 142 页 | 13.52 MB | 1 年前3
 C++高性能并行编程与优化 -  课件 - 05 C++11 开始的多线程编程编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 cpu 缓存机制 8.GPU 专题: wrap 调度,共享内存, barrier 9.并行算法实战: reduce , scan ,矩阵乘法等 10.存储大规模三维数据的关键:稀疏数据结构 11.物理仿真实战:邻居搜索表实现 true 。 • 第二次上锁,由于自己已经上锁,所以失败 了,返回 false 。 只等待一段时间: try_lock_for() • try_lock() 碰到已经上锁的情况,会立即返 回 false 。 • 如果需要等待,但仅限一段时间,可以用 std::timed_mutex 的 try_lock_for() 函数, 他的参数是最长等待时间,同样是由 chrono 指定时间单位。超过这个时间还没0 码力 | 79 页 | 14.11 MB | 1 年前3 C++高性能并行编程与优化 -  课件 - 05 C++11 开始的多线程编程编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 cpu 缓存机制 8.GPU 专题: wrap 调度,共享内存, barrier 9.并行算法实战: reduce , scan ,矩阵乘法等 10.存储大规模三维数据的关键:稀疏数据结构 11.物理仿真实战:邻居搜索表实现 true 。 • 第二次上锁,由于自己已经上锁,所以失败 了,返回 false 。 只等待一段时间: try_lock_for() • try_lock() 碰到已经上锁的情况,会立即返 回 false 。 • 如果需要等待,但仅限一段时间,可以用 std::timed_mutex 的 try_lock_for() 函数, 他的参数是最长等待时间,同样是由 chrono 指定时间单位。超过这个时间还没0 码力 | 79 页 | 14.11 MB | 1 年前3
 Rust 异步并发框架在移动端的应用 - 陈明煜Introduction to third party Runtime crates and their incompatibility with mobile environment Rust 异步机制 Asynchronous Rust 异步并发框架是许多大型应用、系统具备的底层能力。 区别于多线程编程模型,它带来以下优势:  任务调度颗粒度更小,充分利用线程资源  更可控的线程数 async / await  Waker asyn c Future Waker poll Syntax sugar wake await Rust 异步机制 Asynchronous Rust Rust 异步机制 Asynchronous Rust Waker Task Future task Queue wake Worker Future.poll() Reactor0 码力 | 25 页 | 1.64 MB | 1 年前3 Rust 异步并发框架在移动端的应用 - 陈明煜Introduction to third party Runtime crates and their incompatibility with mobile environment Rust 异步机制 Asynchronous Rust 异步并发框架是许多大型应用、系统具备的底层能力。 区别于多线程编程模型,它带来以下优势:  任务调度颗粒度更小,充分利用线程资源  更可控的线程数 async / await  Waker asyn c Future Waker poll Syntax sugar wake await Rust 异步机制 Asynchronous Rust Rust 异步机制 Asynchronous Rust Waker Task Future task Queue wake Worker Future.poll() Reactor0 码力 | 25 页 | 1.64 MB | 1 年前3
 C++高性能并行编程与优化 -  课件 - 06  TBB 开启的并行编程之旅编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 cpu 缓存机制 8.GPU 专题: wrap 调度,共享内存, barrier 9.并行算法实战: reduce , scan ,矩阵乘法等 10.存储大规模三维数据的关键:稀疏数据结构 11.物理仿真实战:邻居搜索表实现 :每个线程一个任务队列,做完本职工作后可以认领其他线程的任务 工作窃取法( work-stealing ) 原始的单一任务队列 解决 4 :随机分配法(通过哈希函数或线性函数) • 然而队列的实现较复杂且需要同步机制,还是有一 定的 overhead ,因此另一种神奇的解法是: • 我们仍是分配 4 个线程,但还是把图像切分为 16 份。然后规定每一份按照 xy 轴坐标位置编号,比 如 (1,3) 等。0 码力 | 116 页 | 15.85 MB | 1 年前3 C++高性能并行编程与优化 -  课件 - 06  TBB 开启的并行编程之旅编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 cpu 缓存机制 8.GPU 专题: wrap 调度,共享内存, barrier 9.并行算法实战: reduce , scan ,矩阵乘法等 10.存储大规模三维数据的关键:稀疏数据结构 11.物理仿真实战:邻居搜索表实现 :每个线程一个任务队列,做完本职工作后可以认领其他线程的任务 工作窃取法( work-stealing ) 原始的单一任务队列 解决 4 :随机分配法(通过哈希函数或线性函数) • 然而队列的实现较复杂且需要同步机制,还是有一 定的 overhead ,因此另一种神奇的解法是: • 我们仍是分配 4 个线程,但还是把图像切分为 16 份。然后规定每一份按照 xy 轴坐标位置编号,比 如 (1,3) 等。0 码力 | 116 页 | 15.85 MB | 1 年前3
 C++高性能并行编程与优化 -  课件 - 11 现代 CMake 进阶指南find_package(spdlog REQUIRED) 时却 变成预编译链接库的版本。(嗯,其实不是 PUBLIC 而是 INTERFACE ,因为伪对象没有实体) 和古代 CMake 做对比:为什么 PUBLIC 属性的传播机制如此便利 现代 CMake : 古代 CMake : 和 find_package(TBB CONFIG REQUIRED) 有什么区别? 其实更好的是通过 find_package(TBB txt 这个文件。 这文件里面装的就是缓存的变量,删了他就可以让 CMake 强制重新检测一遍所有库和编译器。 build/CMakeCache.txt 的内容 find_package 就用到了缓存机制 变量缓存的意义在于能够把 find_package 找到的库文件位置等信息,储存起来。 这样下次执行 find_package 时,就会利用上次缓存的变量,直接返回。 避免重复执行 cmake -B0 码力 | 166 页 | 6.54 MB | 1 年前3 C++高性能并行编程与优化 -  课件 - 11 现代 CMake 进阶指南find_package(spdlog REQUIRED) 时却 变成预编译链接库的版本。(嗯,其实不是 PUBLIC 而是 INTERFACE ,因为伪对象没有实体) 和古代 CMake 做对比:为什么 PUBLIC 属性的传播机制如此便利 现代 CMake : 古代 CMake : 和 find_package(TBB CONFIG REQUIRED) 有什么区别? 其实更好的是通过 find_package(TBB txt 这个文件。 这文件里面装的就是缓存的变量,删了他就可以让 CMake 强制重新检测一遍所有库和编译器。 build/CMakeCache.txt 的内容 find_package 就用到了缓存机制 变量缓存的意义在于能够把 find_package 找到的库文件位置等信息,储存起来。 这样下次执行 find_package 时,就会利用上次缓存的变量,直接返回。 避免重复执行 cmake -B0 码力 | 166 页 | 6.54 MB | 1 年前3
 Rust分布式账务系统 - 胡宇接受转账请求,转换成 events ● 2. 将 events 送入 Raft 共识,等待 events 被多数节点保存 ● 3. 处理被共识的 events ,更新状态机 (账户表) ● 4. 回调完成请求 账户层: Auticuro 分布式账务系统 1 2 3 4 事务层: Marker 分布式账务系统 A,B,C 在不同分区执行一个事务的 TCC 转账计划 ● 转账计划0 码力 | 27 页 | 12.60 MB | 1 年前3 Rust分布式账务系统 - 胡宇接受转账请求,转换成 events ● 2. 将 events 送入 Raft 共识,等待 events 被多数节点保存 ● 3. 处理被共识的 events ,更新状态机 (账户表) ● 4. 回调完成请求 账户层: Auticuro 分布式账务系统 1 2 3 4 事务层: Marker 分布式账务系统 A,B,C 在不同分区执行一个事务的 TCC 转账计划 ● 转账计划0 码力 | 27 页 | 12.60 MB | 1 年前3
共 18 条
- 1
- 2













