C++高性能并行编程与优化 - 课件 - 10 从稀疏数据结构到量化数据类型unordered_map 来存储 map 基于红黑树,会按照键值排序,需要键值具有 operator< 重载,复杂度 O(logn) C++11 新增的 unordered_map 基于哈希表,不保证顺序但更高效,需要键值能被哈希,复杂度 O(1) 用 unordered_map 按 16x16 分块存储 分块能减少 unordered_map 中存储的表项数量,从而减轻哈 希的压力。但意味着键值在空间上需要具有一定的局域性,否 传统稠密二维数组 无边界稀疏分块哈希表 有了无边界的稀疏网格,再也不用担心二维数组要分配多大了。 坐标可以无限延伸,甚至可以是负数!比如 (-1,2) 等…… 他会自动在写入时分配 16x16 的子网格,称之为叶节点 (leaf node) ,而这里的 unordered_map 就是充当根节点 (root node) 。 图片解释稀疏的好处 传统稠密二维数组 无边界稀疏分块哈希表 此外,还是按需分 这些被写入的部分被称为激活元素 (active element) ,反之则是未激活 (inactive) 。 这就是稀疏的好处,按需分配,自动扩容。 分块则是利用了我们存储的数据常常有着空间局域性的特点,减轻哈希表的压 力,同时在每个块内部也可以快乐地 SIMD 矢量化, CPU 自动预取之类的。 第 2 章:位运算 稀疏的好处:坐标可以是负数 这样即使坐标为负数,或者可以是任意大的坐标,都不会产生越界错误。0 码力 | 102 页 | 9.50 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 07 深入浅出访存优化矢量化的话可能还是要 SOA 或 AOSOA ,比如 hw04 那种的。而 “ pos 和 vel 应该用 SOA 分开存”是没问题的。 • 而且 SOA 在遇到存储不是 vector ,而是稀疏的哈希网格之类索引有一定 开销的数据结构,可能就不适合了。这就是为什么王鑫磊最喜欢 AOSOA :在高层保持 AOS 的统一索引,底层又享受 SOA 带来的矢量化 和缓存行预取等好处……就是随机索引比较麻烦。 他附近的 64 字节都被读取到缓存了,但实际只用到了其中 4 字节,之 后又没用到剩下的 60 字节,导致浪费了 94% 的带宽。 • 虽说连续、顺序访问是最理想的,然而在使用哈希表等数据结构中,不 可避免的会通过哈希函数得到随机的地址来访问,且 Value 类型可能小 于 64 字节,浪费部分带宽。怎么办? 解决:按 64 字节分块地随机访问 • 解决方法就是,把数据按 64 字节大小分块。随0 码力 | 147 页 | 18.88 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 14 C++ 标准库系列课 - 你所不知道的 set 容器一样。虽然你可能注意到这 里的刚好和插入的顺序相反 ?巧合而已,具体怎么顺序 是和 glibc 实现有关的。 • set 基于红黑树实现,相当 于二分查找 树, unordered_set 基于散 列哈希表实现,正是哈希函 数导致了随机的顺序。 不同版本的 set 容器比较 类型 去重 有序 查找 插入 vector × × O(n) O(1) ~ O(n) set √ √ O(logn) O(logn)0 码力 | 83 页 | 10.23 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅GPU 专题: wrap 调度,共享内存, barrier 9.并行算法实战: reduce , scan ,矩阵乘法等 10.存储大规模三维数据的关键:稀疏数据结构 11.物理仿真实战:邻居搜索表实现 pbf 流体求解 12.C++ 在 ZENO 中的工程实践:从 primitive 说起 13.结业典礼:总结所学知识与优秀作业点评 I 硬件要求: 64 位( 32 位时代过去了) 至少 q; 1 2 3 4 解决 3 :每个线程一个任务队列,做完本职工作后可以认领其他线程的任务 工作窃取法( work-stealing ) 原始的单一任务队列 解决 4 :随机分配法(通过哈希函数或线性函数) • 然而队列的实现较复杂且需要同步机制,还是有一 定的 overhead ,因此另一种神奇的解法是: • 我们仍是分配 4 个线程,但还是把图像切分为 16 份。然后规定每一份按照0 码力 | 116 页 | 15.85 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 17 由浅入深学习 map 容器k k k k k k k k k k k k v v v v v v setmap 第四章:哈希散列表 高效的查找离不开我 高效的查找离不开我 unordered_set 查找为什么高效 • 为什么哈希散列表 unorered_set 会比线性数组 vector 在查找这一点上更高效? • 你看,我们刚才只判断了 3 次就找到了目标。这还是最坏的情况,最好只需要 unordered_set 是如何在 O(1) 复杂度内找到任意元素的。 • unordered_map 也一样,只不过是在每个 K 后面外挂了一个 V 类型。 • 计算哈希值时只计算 K 的哈希,而 V 不参与哈希,是个旁观者。 • 查找时,不是返回 K ,而是返回他后面挂的 V ,是个冒名者。 • 就是说,苦劳都是 K 的,功劳都是 V 的。就这两点区别,示意图: k k v unordered_set 0 码力 | 90 页 | 8.76 MB | 1 年前3
谈谈MYSQL那点事MyISAM vs InnoDB InnoDB • 数据存储方式简单,使用 数据存储方式简单,使用 B+ Tree B+ Tree 进行索引 进行索引 • 使用三个文件定义一个表: 使用三个文件定义一个表: .MYI .MYD .frm .MYI .MYD .frm • 少碎片、支持大文件、能够进行索引压缩 少碎片、支持大文件、能够进行索引压缩 • 二进制层次的文件可以移植 设计合理架构,如果 设计合理架构,如果 MySQL MySQL 访问频繁,考虑 访问频繁,考虑 Master/Slave Master/Slave 读写分离;数据库分表、数据库切片(分 读写分离;数据库分表、数据库切片(分 布式),也考虑使用相应缓存服务帮助 布式),也考虑使用相应缓存服务帮助 MySQL MySQL 缓解访问 缓解访问 压力 压力 系统优化 系统优化 起作用 record_buffer 128K 64M 每个进行一个顺序扫描的线程为其扫描的每 张表分配这个大小的一个缓冲区,可以设置 为 2M 以上 table_cache 64 1024 为所有线程打开表的数量。增加该值能增加 mysqld 要求的文件描述符的数量。 MySQL 对每个唯一打开的表需要 2 个文件描述符。 服务优化 服务优化 MyISAM MyISAM 选项 选项 选项0 码力 | 38 页 | 2.04 MB | 1 年前3
基于 Rust Arrow Flight 的物联网和时序数据传输及转换工具 霍琳贺系统功能,能大幅减少系统设计的复杂度,降低研发和运营成本,是一个极简的时序数据处理平台。 采用关系型数据库模型 需要建库、建表, 为提升写入和查询效率,要求一个数据采集点一张表 为实现多表聚合,引入超级表概念 子表通过超级表创建,带有标签,通过标签实现多表 高效聚合 高效写入 支持标准 SQL 写入,支持批量写入 支持 Schemaless 写入 多个国家安装实例超 270k | GitHub 全球趋势排行榜多次排名第一 TDengine - 数据模型 1. 设备 ID 及关联属性( Tags ) 2. 时间戳 3. 结构化采集量 STable 超级表 Table 子表 CREATE STABLE `meters` ( `ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase`0 码力 | 29 页 | 2.26 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 性能优化之无分支编程 Branchless Programmingcom/x86/cmovcc https://www.felixcloutier.com/x86/setcc https://www.felixcloutier.com/x86/jcc 条件后缀一览表 后缀 含义 英文全称 le 小于等于(有符号) less or equal ge 大于等于(有符号) greater or equal l 小于(有符号) less g 大于(有符号) greater ,他都会想方设法帮你优化成查表 法。 • 所以不用纠结性能,你觉得哪种写起来可 读性强,容易维护,你就怎么写。 无分支优化的方法:查表法 • 如果每个判断的值是连续的,这种情况一般 会建立一个表(数组)。 • 这个表里每个元素就是原来要返回的一个个 值,索引就是要判断的参数 x 。 • 因为查表只需要一个指针的加法和读取操作 ,复杂度是 O(1) 的;运算量远远小于最坏 需要 n 次判断的一堆 注:实际中虚函数往往有很多个,为了存储空间的高效利用,会把多个虚函数打包成一个数组,称之 为“虚函数表( vtable )”。这样一来,类成员里只需要存一个指向虚函数表首地址的指针,之后通过 查找该表即可找到连续的 n 个函数指针。此处为了方便理解,右侧案例代码没有用虚函数表。 课外拓展 · 参考资料 • 堆栈和 ABI 的知识 https://zhuanlan.zhihu.com/p/273391910 码力 | 47 页 | 8.45 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 12 从计算机组成原理看 C 语言指针std::size , std::data , std::ne xt • 懂我意思吧?你永远猜不到他们玄学名字能多短。 • 一不小心就和你现有的函数撞名了,你根本搞不清 。 常用函数名称一览表 int long long long float double C++ 重载版 abs labs llabs fabsf fabs std::abs - - - fmaxf fmax std::max 4 就不可省略。 指向数组其中一个元素的指针 • 我们说过,变量的地址(也就是指针)可以通 过 & 获取,例如 &x 表示变量 x 的指针。 • 因为数组的每个元素都是一个变量, &a[0] 表 示数组 a 第 0 个元素的地址。 指向数组其中一个元素的指针 • 同理, &a[1] 就是第 1 个元素(按照人类的 思维是第二个元素)的地址。 修改指针指向的地址,使其加 1 ,会怎么样? 对照表,他们把英文字符 和一些标点符号逐个对应到一个 0~127 的整数,这也正好是 char 类型在正数部 分的表示范围。这就是为什么 char 类型 实际上就是个 8 位有符号整数,却可以表 示字符。 • 那么 -128~-1 的范围都用来做什么了呢?好问 题,他们其实被用来表示汉字和其他字符了, 而且是两个 char 一组的方式,我们择日再讨 论。 https://en.wikipedia0 码力 | 128 页 | 2.95 MB | 1 年前3
Rust分布式账务系统 - 胡宇events ,更新状态机 (账户表) ○ 去重 & 更新余额 ○ 关键路径采用无锁单线程 账户层: Auticuro 分布式账务系统 1 2 3 4 ● 1. 接受转账请求,转换成 events ● 2. 将 events 送入 Raft 共识,等待 events 被多数节点保存 ● 3. 处理被共识的 events ,更新状态机 (账户表) ● 4. 回调完成请求 账户层:0 码力 | 27 页 | 12.60 MB | 1 年前3
共 17 条
- 1
- 2













