新一代分布式高性能图数据库的构建 - 沈游人
拥有 拥有 持有 登录 / 连接 已购买 / 意向购 买 / 潜在购买 /... 个人 客户 账户 机构 客户 资产 合约 员工 手机号 设备 商品 商品 查询 / 操作 生活中无处不在的图 图分析技术分类 图查询 • 使用图数据库的查询语言进行点边搜索 图算法 • 中心性算法 • 社区算法 • 路径算法 • … 图深度学习 • 图嵌入 • 图卷积 • 好的加速效果 • 要想让内存缓存发挥最大的作用,就要能在有限的内存中存下尽量多的图数据 • 例如,对于属性的存储,可以通过自行序列化 / 反序列化大幅节省内存 • 而自定义存储格式往往需要内存的精细操作,由于 Rust 允许在 unsafe 下访问裸指针, 可以实现零开销读取 • 将 Unsafe 包裹,对外提供足够的接口 i32 i64 u32 u32 string string 定长 变长 命令行客户端 WebUI 面向分析师,提供图模型定义、数据管理、图查询分析、服务状态监控、用户管理能力 免代码,可视化定义实体、 边,设计图模型。 【亮点】 • 支持模型导入导出 • 拖拽式关系构建 • 丰富的样式配置 • 实时图结构预览 • 用户授权管理 • 中文及显示别名支持 图模型设计 WebUI—— 可视化图探索分析 【亮点】 • K 步邻居查询、属性过滤 •0 码力 | 38 页 | 24.68 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程
同理,还有 cudaMemcpyHostToDevice 和 cudaMemcpyDeviceToDevice 。 cudaMemcpy 会自动同步! • 注意: cudaMemcpy 会自动进行同步操作 ,即和 cudaDeviceSynchronize() 等价! 因此前面的 cudaDeviceSynchronize() 实 际上可以删掉了。 统一内存地址技术( Unified Memory allocate/deallocate 成员函数的类,这样就可以“骗过” vector , 让他不是在 CPU 内存中分配,而是在 CUDA 的统一内存 (managed) 上分配。 • 实际上这种“骗”来魔改类内部行为的操作,正是现代 C++ 的 concept 思想所在。因此替换 allocator 实际上是标准库允许的 ,因为他提升了标准库的泛用性。 进一步:避免初始化为 0 • vector 在初始化的时候(或是之后 C++03 , B 站 / 油管偶尔翻出几个介绍 C++11 新特性的视频已经算很先进很前卫了,然而现在 C++23 的标准都已经开始往官网上挂了…… 第 7 章:原子操作 经典案例:数组求和 • 如何并行地对数组进行求和操作? • 首先让我们试着用串行的思路来解题。 • 因为 __global__ 函数不能返回值,只能 通过指针。因此我们先分配一个大小为 1 的 sum 数组,其中0 码力 | 142 页 | 13.52 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 07 深入浅出访存优化
次浮点读写 ≈ 8 次浮点加法 • 如果矢量化成功( SSE ): 1 次浮点读写 ≈ 32 次浮点加法 • 如果 CPU 有 4 核且矢量化成功: 1 次浮点读写 ≈ 128 次浮点加 法 常见操作所花费的时间 • 图中加法 (add) 和乘法 (mul) 都指的整数。 • 区别是浮点的乘法和加法基本是一样速度。 • L1/2/3 read 和 Main RAM read 的时间指的是 个缓存行,而不是一个。 • 这样一次随机访问之后会伴随着 64 次顺序访问, 能被 CPU 检测到,从而启动缓存行预取,避免了 等待数据抵达前空转浪费时间。 页对齐的重要性 • 为什么要 4KB ?原来现在操作系统管理内存是用分页 ( page ),程序的内存是一页一页贴在地址空间中的, 有些地方可能不可访问,或者还没有分配,则把这个页设 为不可用状态,访问他就会出错,进入内核模式。 • 因此硬件 倍左右,大家掌握里面的思想就好。 进一步优化 • 用了一些常量作为参数,调整一下局部数组的大小。 • 加速比: 16 倍,大概已经到极限了? 进亿步优化 • 将两个方法一起用上,并用 stream_ps 防止 写回操作污染缓存。 • 最终加速比: 24 倍。这里可以看到 i - 2 和 i + 2 跨步的访存似乎不是很理想,可能还能 进亿步优化,出于时间原因就没继续深入, 同学们可以课后研究一下。 第0 码力 | 147 页 | 18.88 MB | 1 年前3谈谈MYSQL那点事
不支持一些数据库特性,比如 事务、外键约束等 不支持一些数据库特性,比如 事务、外键约束等 • Table level lock Table level lock ,性能稍差,更适合读取多的操作 ,性能稍差,更适合读取多的操作 InnoDB InnoDB 特点 特点 •使用 使用 Table Space Table Space 的方式来进行数据存储 的方式来进行数据存储 (ibdata1, ib_logfile0) MySQL 优化方式 优化方式 影响性能的因素 影响性能的因素 应用程序 应用程序 查询 查询 事务管理 事务管理 数据库设计 数据库设计 数据分布 数据分布 网络 网络 操作系统 操作系统 硬件 硬件 使用好的硬件,更快的硬盘、大内存、多核 使用好的硬件,更快的硬盘、大内存、多核 CPU CPU ,专业的 ,专业的 存储服务器( 存储服务器( NAS NAS 、 、 像性别、状态值等等建立索引没有意义 像性别、状态值等等建立索引没有意义 字段唯一,最少,不可为 字段唯一,最少,不可为 null null 对大数据量表建立聚集索引,避免更新操作带来的碎片。 对大数据量表建立聚集索引,避免更新操作带来的碎片。 尽量使用短索引,一般对 尽量使用短索引,一般对 int int 、 、 char/varchar char/varchar 、 、 date/tim0 码力 | 38 页 | 2.04 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 10 从稀疏数据结构到量化数据类型
)不一定就是完美解决方案,要根据实际情况判断。 真正的解决: tbb::spin_mutex 其实主要的瓶颈在于 std::mutex 会切换到操作系统内核中去调度 ,非常低效。而 tbb::spin_mutex 则是基于硬件原子指令的,完全 用户态的实现。区别: std::mutex 的陷入等待会让操作系统挂起 该线程,以切换到另一个;而 tbb::spin_mutex 的陷入等待是通过 不断地 while (locked); uantaichi.pdf ← ??? 第 7 章: SPGrid 操作系统管理内存的最小单位:页( 4KB ) • 当调用 malloc 时,操作系统并不会实际分配那一块内存,而是将这一段内存标记为“不可 用”。当用户试图访问(写入)这一片内存时,硬件就会触发所谓的缺页中断( page fault ),进入操作系统内核,内核会查找当前进程的 malloc 历史记录。如果发现用户写 入的地址是他曾经 用户写入的地址根本不是他 malloc 过的 地址,那就说明他确实犯错了,就抛出段错误( segmentation fault )。 • 当一个尚且处于“不可用”的 malloc 过的区间被访问,操作系统不是把整个区间全部分配完 毕,而是只把当前写入地址所在的页面( 4KB 大小)给分配上。也就是说用户访问 a[0] 以后只分配了 4KB 的内存。等到用户访问了 a[1024] ,也就是触及了下一个页面,他才0 码力 | 102 页 | 9.50 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 05 C++11 开始的多线程编程
std::milli> 的别名 跨平台的 sleep : std::this_thread::sleep_for • 可以用 std::this_thread::sleep_for 替代 Unix 类操作系统专有的的 usleep 。他可 以让当前线程休眠一段时间,然后继续。 • 而且单位也可以自己指定,比如这里是 milliseconds 表示毫秒,也可以换成 microseconds • 除了接受一个时间段的 sleep_for ,还有 接受一个时间点的 sleep_until ,表示让当 前线程休眠直到某个时间点。 第 1 章:线程 进程与线程 • 进程是一个应用程序被操作系统拉起来加载到内存之后从开始执行到执行结束的这样一个 过程。简单来说,进程是程序(应用程序,可执行文件)的一次执行。比如双击打开一个 桌面应用软件就是开启了一个进程。 • 线程是进程中的一个实 我们的程序常常需要同时处理多个任务。 • 例如:后台在执行一个很耗时的任务,比 如下载一个文件,同时还要和用户交互。 • 这在 GUI 应用程序中很常见,比如浏览 器在后台下载文件的同时,用户仍然可以 用鼠标操作其 UI 界面。 没有多线程:程序未响应 • 没有多线程的话,就必须等文件下载完了 才能继续和用户交互。 • 下载完成前,整个界面都会处于“未响应”状 态,用户想做别的事情就做不了。 现代0 码力 | 79 页 | 14.11 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 13 C++ STL 容器全解之 vector
• 值得注意的是, [] 运算符在索引超出数组大 小时并不会直接报错,这是为了性能的考虑。 • 如果你不小心用 [] 访问了越界的索引,可能 会覆盖掉别的变量导致程序行为异常,或是访 问到操作系统未映射的区域导致奔溃。 • int &operator[](size_t i) noexcept; • int const &operator[](size_t i) const noexcept; 迭代器入门 迭代器模式 • 如果要把右边这个打印的操作封装起来, 该怎么做? 迭代器模式 • 如果要把右边这个打印的操作封装起来, 该怎么做? • 可以用一个函数来封装打印操作: • print(vectorconst &a); 迭代器模式 • 如果要把右边这个打印的操作封装起来, 该怎么做? • 可以用一个函数来封装打印操作: • print(vector 因此可改用首地址指针和数组长度做参数 : • print(char const *a, size_t n); • 这样 print 在无需知道容器具体类型的情 况下,只用最简单的接口(首地址指针) 就完成了遍历和打印的操作。 迭代器模式 • 使用指针和长度做接口的好处是,可以通 过给指针加减运算,选择其中一部分连续 的元素来打印,而不一定全部打印出来。 • 比如这里我们选择打印前三个元素(去掉 了最后一个元素,但不必用 0 码力 | 90 页 | 4.93 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 15 C++ 系列课:字符与字符串
• % 就像你和同学随手“拉钩”定下的约定,这是 printf 约定俗成的。 • \ 就像正式合同,有法律效力的,这是 C 语言编译器规定好的。 C++ 字符串类 第 3 章 C 语言字符串操作繁琐 封装的 std::string 应运而生 封装的 std::string 应运而生 • string 可以从 const char * 隐式构造: • string s = “hello”; 内部定义一览 std::literials::string_literials std::literials::chrono_literials 字符串 <--> 数字 第 4 章 java 经典操作:字符串 + 数字 = 字符串 • 在 java 中,你甚至可以直接把字符串和数字相加,例如: • “you have ” + 42 + “ yuan” 会得到 “ you have 42 yuan” stoi/stof/stod 。 • 最重要的是他支持各种控制选项(如 hex ), 功能性比 to_string 和 stoi 更强大。 • 要导入他,只需 #include即可。 字符串常用操作 第 6 章 at 获取指定位置的字符 • s.at(i) 和 s[i] 都可以获取字符串中的第 i 个字符。 • 区别在于 at 如果遇到 i 越界的情况,也就是检测到 i ≥ s.size() 0 码力 | 162 页 | 40.20 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 12 从计算机组成原理看 C 语言指针
表示不下,则自动选择较大的类型 标准化的类型: stdint.h • 而实际上,尽管主流操作系统上 int 都是 32 位的, C 语言标准并没有规定 int 就是 32 位 的。 • int 甚至可以是 16 位的!只不过主流操作系统一致认为是 32 位的而已,并不是标准所保 证的。 • 为了解决不同操作系统上对类型定义混乱的问题, C 语言标准引入了 stdint.h 这个头文件 。 他里面包含一系列类型别名 (typedef) ,这些别名保证不论是什么操作系统什么架构,都是 固定的大小,例如: • typedef char int8_t; • typedef short int16_t; • typedef int int32_t; • typedef long long int64_t; • 这样不论操作系统对类型的定义如何混乱,这些标准化的类型都是确定的大小。 • size_t 这个直观的名字,他和 uintptr_t 等价 。 • size_t 是标准库大量使用的用于表示大小的类型,例如 vector::size() 返回类型就是 size_t 。 • 在主流操作系统上, size_t 和 uintptr_t 完全等价,虽然标准并没有强制要求这一点。 • 此外还有有符号的 ssize_t 和 intptr_t 等价,不过他是 Unix/Linux 系统特有的,0 码力 | 128 页 | 2.95 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 11 现代 CMake 进阶指南
目录再切换进去再指定源码目录的麻烦。 • cmake --build build 统一了不同平台( Linux 上会调用 make , Windows 上调用 devenv.exe ) • 结论:从现在开始,如果在命令行操作 cmake ,请使用更方便的 -B 和 --build 命令。 // 在源码目录用 -B 直接创建 build 目录并生成 build/Makefile // 自动调用本地的构建系统在 build 过去的软件(例如 TBB )要跨平台,只好 Makefile 的构建规则写一份, MSBuild 也写一份 。 • 现在只需要写一次 CMakeLists.txt ,他会视不同的操作系统,生成不同构建系统的规则文件。 • 那个和操作系统绑定的构建系统( make 、 MSBuild )称为本地构建系统( native buildsystem )。 • 负责从 CMakeLists.txt 生成本地构建系统构建规则文件的,称为生成器( scivision.dev/cmake-object-libraries/ 对象库类似于静态库,但不生成 .a 文件,只由 CMake 记住该库生成了哪些对象文件 对象库是 CMake 自创的,绕开了编译器和操作系统的各种繁琐规则,保证了跨平台统一性 。 在自己的项目中,我推荐全部用对象库 (OBJECT) 替代静态库 (STATIC) 避免跨平台的麻烦 。 对象库仅仅作为组织代码的方式,而实际生成的可执行文件只有一个,减轻了部署的困难。0 码力 | 166 页 | 6.54 MB | 1 年前3
共 24 条
- 1
- 2
- 3