 Hello 算法 1.0.0b1 C++版平方阶常见于元素数量与 ? 成平方关系的矩阵、图。 // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector Hello 算法 1.0.0b1 C++版平方阶常见于元素数量与 ? 成平方关系的矩阵、图。 // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector- > numMatrix; 2. 复杂度分析 hello‑algo.com 32 for (int i = 0; i < n; i++) 算法运行中,相关数据都被存储在内存中。下图展示了一个计算机内存条,其中每个黑色方块都包含一块内存 空间。我们可以将内存想象成一个巨大的 Excel 表格,其中每个单元格都可以存储 1 byte 的数据,在算法运 行时,所有数据都被存储在这些单元格中。 系统通过「内存地址 Memory Location」来访问目标内存位置的数据。计算机根据特定规则给表格中每个 单元格编号,保证每块内存空间都有独立的内存地 updateHeight(node); updateHeight(child); // 返回旋转后子树的根结点 return child; } Case 2 ‑ 左旋 类似地,如果将取上述失衡二叉树的“镜像”,那么则需要「左旋」操作。 7. 树 hello‑algo.com 115 Figure 7‑27. 左旋操作 同理,若结点 child 本身有左子结点(记为 grandChild ),则需要在「左旋」中添加一步:将 0 码力 | 187 页 | 14.71 MB | 1 年前3
 Hello 算法 1.0.0b2 C++版平方阶常见于元素数量与 ? 成平方关系的矩阵、图。 // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector Hello 算法 1.0.0b2 C++版平方阶常见于元素数量与 ? 成平方关系的矩阵、图。 // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector- > numMatrix; 2. 复杂度分析 hello‑algo.com 32 for (int i = 0; i < n; i++) 算法运行中,相关数据都被存储在内存中。下图展示了一个计算机内存条,其中每个黑色方块都包含一块内存 空间。我们可以将内存想象成一个巨大的 Excel 表格,其中每个单元格都可以存储 1 byte 的数据,在算法运 行时,所有数据都被存储在这些单元格中。 系统通过「内存地址 Memory Location」来访问目标内存位置的数据。计算机根据特定规则给表格中每个 单元格编号,保证每块内存空间都有独立的内存地 updateHeight(node); updateHeight(child); // 返回旋转后子树的根结点 return child; } Case 2 ‑ 左旋 类似地,如果将取上述失衡二叉树的“镜像”,那么则需要「左旋」操作。 7. 树 hello‑algo.com 115 Figure 7‑27. 左旋操作 同理,若结点 child 本身有左子结点(记为 grandChild ),则需要在「左旋」中添加一步:将 0 码力 | 197 页 | 15.72 MB | 1 年前3
 C++高性能并行编程与优化 -  课件 - 09 CUDA C++ 流体仿真实战用于分配一个三维数组。 各维度上的大小通过 cudaExtent 指定,方 便起见我们的 C++ 封装类用了 uint3 表示 大小。 • GPU 的多维数组有特殊的数据排布来保障 访存的高效,和我们 CPU 那样简单地行主 序或列主序(如 a[x + nx * y] )的多维数组 不一样。 • 随后可用 cudaMemcpy3D 在 GPU 的三 维数组和 CPU 的三维数组之间拷贝数据。 tex3D 来读取纹理中的值。 • 之所以纹理是因为 GPU 一开始是渲染图形的专用硬件 ,会用到一些贴图等,这就是二维的纹理。 • 当输入的浮点坐标不是整数时,由 GPU 硬件提供双线 性插值( bilerp ),比手写的高效许多。 • 当然如果是三维数组,那就是三维纹理对象,访问时是 提供三线性插值( trilerp )的。 CUDA 纹理对象:封装 • 其中 cudaTextureAddressMode 示意: 00 | ABCDE | 00 • cudaAddressModeWrap :重叠模式(循环) • 示意: DE | ABCDE | AB • cudaAddressModeMirror :镜像模式 • 示意: BA | ABCDE | ED CUDA 纹理对象:封装 • 其中 cudaTextureFilterMode 表示采样的坐标不是整数 时要如何在周围 8 个值之间插值,有以下几种选择:0 码力 | 58 页 | 14.90 MB | 1 年前3 C++高性能并行编程与优化 -  课件 - 09 CUDA C++ 流体仿真实战用于分配一个三维数组。 各维度上的大小通过 cudaExtent 指定,方 便起见我们的 C++ 封装类用了 uint3 表示 大小。 • GPU 的多维数组有特殊的数据排布来保障 访存的高效,和我们 CPU 那样简单地行主 序或列主序(如 a[x + nx * y] )的多维数组 不一样。 • 随后可用 cudaMemcpy3D 在 GPU 的三 维数组和 CPU 的三维数组之间拷贝数据。 tex3D 来读取纹理中的值。 • 之所以纹理是因为 GPU 一开始是渲染图形的专用硬件 ,会用到一些贴图等,这就是二维的纹理。 • 当输入的浮点坐标不是整数时,由 GPU 硬件提供双线 性插值( bilerp ),比手写的高效许多。 • 当然如果是三维数组,那就是三维纹理对象,访问时是 提供三线性插值( trilerp )的。 CUDA 纹理对象:封装 • 其中 cudaTextureAddressMode 示意: 00 | ABCDE | 00 • cudaAddressModeWrap :重叠模式(循环) • 示意: DE | ABCDE | AB • cudaAddressModeMirror :镜像模式 • 示意: BA | ABCDE | ED CUDA 纹理对象:封装 • 其中 cudaTextureFilterMode 表示采样的坐标不是整数 时要如何在周围 8 个值之间插值,有以下几种选择:0 码力 | 58 页 | 14.90 MB | 1 年前3
 Hello 算法 1.0.0b4 C++版平方阶常见于矩阵和图,元素数量与 ? 成平方关系。 // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector Hello 算法 1.0.0b4 C++版平方阶常见于矩阵和图,元素数量与 ? 成平方关系。 // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector- > numMatrix; for (int i = 0; i < n; i++) { vector - tmp; for 据都是以数组的形式 构建的。数组是神经网络编程中最常使用的数据结构。 ‧ 数据结构实现:数组可以用于实现栈、队列、哈希表、堆、图等数据结构。例如,邻接矩阵是图的常见 表示之一,它实质上是一个二维数组。 4. 数组与链表 hello‑algo.com 55 4.2. 链表 内存空间是所有程序的公共资源,排除已被占用的内存空间,空闲内存空间通常散落在内存各处。在上一节 中,我们提到存储数 updateHeight(node); updateHeight(child); // 返回旋转后子树的根节点 return child; } 左旋 相应的,如果考虑上述失衡二叉树的“镜像”,则需要执行「左旋」操作。 7. 树 hello‑algo.com 141 Figure 7‑28. 左旋操作 同理,若节点 child 本身有左子节点(记为 grandChild ),则需要在「左旋」中添加一步:将 0 码力 | 343 页 | 27.39 MB | 1 年前3
 Hello 算法 1.1.0 C++ 版靠地求得问题的正确解。 2. 寻求最优解法:同一个问题可能存在多种解法,我们希望找到尽可能高效的算法。 也就是说,在能够解决问题的前提下,算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维 度。 ‧ 时间效率:算法运行速度的快慢。 ‧ 空间效率:算法占用内存空间的大小。 简而言之,我们的目标是设计“既快又省”的数据结构与算法。而有效地评估算法效率至关重要,因为只有 这样,我们 com 22 图 2‑2 嵌套循环的流程框图 在这种情况下,函数的操作数量与 ?2 成正比,或者说算法运行时间和输入数据大小 ? 成“平方关系”。 我们可以继续添加嵌套循环,每一次嵌套都是一次“升维”,将会使时间复杂度提高至“立方关系”“四次方 关系”,以此类推。 2.2.2 递归 递归(recursion)是一种算法策略,通过函数调用自身来解决问题。它主要包含两个阶段。 1. 递:程序 平方阶常见于矩阵和图,元素数量与 ? 成平方关系: // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector Hello 算法 1.1.0 C++ 版靠地求得问题的正确解。 2. 寻求最优解法:同一个问题可能存在多种解法,我们希望找到尽可能高效的算法。 也就是说,在能够解决问题的前提下,算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维 度。 ‧ 时间效率:算法运行速度的快慢。 ‧ 空间效率:算法占用内存空间的大小。 简而言之,我们的目标是设计“既快又省”的数据结构与算法。而有效地评估算法效率至关重要,因为只有 这样,我们 com 22 图 2‑2 嵌套循环的流程框图 在这种情况下,函数的操作数量与 ?2 成正比,或者说算法运行时间和输入数据大小 ? 成“平方关系”。 我们可以继续添加嵌套循环,每一次嵌套都是一次“升维”,将会使时间复杂度提高至“立方关系”“四次方 关系”,以此类推。 2.2.2 递归 递归(recursion)是一种算法策略,通过函数调用自身来解决问题。它主要包含两个阶段。 1. 递:程序 平方阶常见于矩阵和图,元素数量与 ? 成平方关系: // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector- > numMatrix; for (int i = 0; i < n; i++) { vector - tmp; for 0 码力 | 379 页 | 18.47 MB | 1 年前3
 Hello 算法 1.0.0 C++版靠地求得问题的正确解。 2. 寻求最优解法:同一个问题可能存在多种解法,我们希望找到尽可能高效的算法。 也就是说,在能够解决问题的前提下,算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维 度。 ‧ 时间效率:算法运行速度的快慢。 ‧ 空间效率:算法占用内存空间的大小。 简而言之,我们的目标是设计“既快又省”的数据结构与算法。而有效地评估算法效率至关重要,因为只有 这样,我们 com 22 图 2‑2 嵌套循环的流程框图 在这种情况下,函数的操作数量与 ?2 成正比,或者说算法运行时间和输入数据大小 ? 成“平方关系”。 我们可以继续添加嵌套循环,每一次嵌套都是一次“升维”,将会使时间复杂度提高至“立方关系”“四次方 关系”,以此类推。 2.2.2 递归 「递归 recursion」是一种算法策略,通过函数调用自身来解决问题。它主要包含两个阶段。 1. 递:程 平方阶常见于矩阵和图,元素数量与 ? 成平方关系: // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector Hello 算法 1.0.0 C++版靠地求得问题的正确解。 2. 寻求最优解法:同一个问题可能存在多种解法,我们希望找到尽可能高效的算法。 也就是说,在能够解决问题的前提下,算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维 度。 ‧ 时间效率:算法运行速度的快慢。 ‧ 空间效率:算法占用内存空间的大小。 简而言之,我们的目标是设计“既快又省”的数据结构与算法。而有效地评估算法效率至关重要,因为只有 这样,我们 com 22 图 2‑2 嵌套循环的流程框图 在这种情况下,函数的操作数量与 ?2 成正比,或者说算法运行时间和输入数据大小 ? 成“平方关系”。 我们可以继续添加嵌套循环,每一次嵌套都是一次“升维”,将会使时间复杂度提高至“立方关系”“四次方 关系”,以此类推。 2.2.2 递归 「递归 recursion」是一种算法策略,通过函数调用自身来解决问题。它主要包含两个阶段。 1. 递:程 平方阶常见于矩阵和图,元素数量与 ? 成平方关系: // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector- > numMatrix; for (int i = 0; i < n; i++) { vector - tmp; for 0 码力 | 378 页 | 17.59 MB | 1 年前3
 Hello 算法 1.0.0b5 C++版靠地求得问题的正确解。 2. 寻求最优解法:同一个问题可能存在多种解法,我们希望找到尽可能高效的算法。 也就是说,在能够解决问题的前提下,算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维 度。 ‧ 时间效率:算法运行速度的快慢。 ‧ 空间效率:算法占用内存空间的大小。 简而言之,我们的目标是设计“既快又省”的数据结构与算法。而有效地评估算法效率至关重要,因为只有 这样我们才 com 21 图 2‑2 嵌套循环的流程框图 在这种情况下,函数的操作数量与 ?2 成正比,或者说算法运行时间和输入数据大小 ? 成“平方关系”。 我们可以继续添加嵌套循环,每一次嵌套都是一次“升维”,将会使时间复杂度提高至“立方关系”、“四次方 关系”、以此类推。 2.2.2 递归 「递归 recursion」是一种算法策略,通过函数调用自身来解决问题。它主要包含两个阶段。 1. 递: 平方阶常见于矩阵和图,元素数量与 ? 成平方关系: // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector Hello 算法 1.0.0b5 C++版靠地求得问题的正确解。 2. 寻求最优解法:同一个问题可能存在多种解法,我们希望找到尽可能高效的算法。 也就是说,在能够解决问题的前提下,算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维 度。 ‧ 时间效率:算法运行速度的快慢。 ‧ 空间效率:算法占用内存空间的大小。 简而言之,我们的目标是设计“既快又省”的数据结构与算法。而有效地评估算法效率至关重要,因为只有 这样我们才 com 21 图 2‑2 嵌套循环的流程框图 在这种情况下,函数的操作数量与 ?2 成正比,或者说算法运行时间和输入数据大小 ? 成“平方关系”。 我们可以继续添加嵌套循环,每一次嵌套都是一次“升维”,将会使时间复杂度提高至“立方关系”、“四次方 关系”、以此类推。 2.2.2 递归 「递归 recursion」是一种算法策略,通过函数调用自身来解决问题。它主要包含两个阶段。 1. 递: 平方阶常见于矩阵和图,元素数量与 ? 成平方关系: // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector- > numMatrix; for (int i = 0; i < n; i++) { vector - tmp; for 0 码力 | 377 页 | 30.69 MB | 1 年前3
 Hello 算法 1.2.0 简体中文 C++ 版靠地求得问题的正确解。 2. 寻求最优解法:同一个问题可能存在多种解法,我们希望找到尽可能高效的算法。 也就是说,在能够解决问题的前提下,算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维 度。 ‧ 时间效率:算法运行时间的长短。 ‧ 空间效率:算法占用内存空间的大小。 简而言之,我们的目标是设计“既快又省”的数据结构与算法。而有效地评估算法效率至关重要,因为只有 这样,我们 com 22 图 2‑2 嵌套循环的流程框图 在这种情况下,函数的操作数量与 ?2 成正比,或者说算法运行时间和输入数据大小 ? 成“平方关系”。 我们可以继续添加嵌套循环,每一次嵌套都是一次“升维”,将会使时间复杂度提高至“立方关系”“四次方 关系”,以此类推。 2.2.2 递归 递归(recursion)是一种算法策略,通过函数调用自身来解决问题。它主要包含两个阶段。 1. 递:程序 平方阶常见于矩阵和图,元素数量与 ? 成平方关系: // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector Hello 算法 1.2.0 简体中文 C++ 版靠地求得问题的正确解。 2. 寻求最优解法:同一个问题可能存在多种解法,我们希望找到尽可能高效的算法。 也就是说,在能够解决问题的前提下,算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维 度。 ‧ 时间效率:算法运行时间的长短。 ‧ 空间效率:算法占用内存空间的大小。 简而言之,我们的目标是设计“既快又省”的数据结构与算法。而有效地评估算法效率至关重要,因为只有 这样,我们 com 22 图 2‑2 嵌套循环的流程框图 在这种情况下,函数的操作数量与 ?2 成正比,或者说算法运行时间和输入数据大小 ? 成“平方关系”。 我们可以继续添加嵌套循环,每一次嵌套都是一次“升维”,将会使时间复杂度提高至“立方关系”“四次方 关系”,以此类推。 2.2.2 递归 递归(recursion)是一种算法策略,通过函数调用自身来解决问题。它主要包含两个阶段。 1. 递:程序 平方阶常见于矩阵和图,元素数量与 ? 成平方关系: // === File: space_complexity.cpp === /* 平方阶 */ void quadratic(int n) { // 二维列表占用 O(n^2) 空间 vector- > numMatrix; for (int i = 0; i < n; i++) { vector - tmp; for 0 码力 | 379 页 | 18.48 MB | 10 月前3
 C++高性能并行编程与优化 -  课件 - 06  TBB 开启的并行编程之旅被忽视的访存优化:内存带宽与 cpu 缓存机制 8.GPU 专题: wrap 调度,共享内存, barrier 9.并行算法实战: reduce , scan ,矩阵乘法等 10.存储大规模三维数据的关键:稀疏数据结构 11.物理仿真实战:邻居搜索表实现 pbf 流体求解 12.C++ 在 ZENO 中的工程实践:从 primitive 说起 13.结业典礼:总结所学知识与优秀作业点评 ,其中 c 是线程数量 封装好了: parallel_for 面向初学者: parallel_for 基于迭代器区间: parallel_for_each 二维区间上的 for 循环: blocked_range2d 三维区间上的 for 循环: blocked_range3d 所有区间类型 第 2 章:缩并与扫描 缩并( reduce ) 1 个线程,依次处理 8 个元素的缩并,花了 ,需要做大量数学运算,因此瓶颈在 ALU 。 • 这里卖个关子,欲知后事如何,请待下集揭晓! 更专业的性能测试框架: Google benchmark • 手动计算时间差有点太硬核了,而且只运 行一次的结果可能不准确,最好是多次运 行取平均值才行。 • 因此可以利用谷歌提供的这个框架。 • 只需将你要测试的代码放在他的 • for (auto _: bm) • 里面即可。他会自动决定要重复多少次,0 码力 | 116 页 | 15.85 MB | 1 年前3 C++高性能并行编程与优化 -  课件 - 06  TBB 开启的并行编程之旅被忽视的访存优化:内存带宽与 cpu 缓存机制 8.GPU 专题: wrap 调度,共享内存, barrier 9.并行算法实战: reduce , scan ,矩阵乘法等 10.存储大规模三维数据的关键:稀疏数据结构 11.物理仿真实战:邻居搜索表实现 pbf 流体求解 12.C++ 在 ZENO 中的工程实践:从 primitive 说起 13.结业典礼:总结所学知识与优秀作业点评 ,其中 c 是线程数量 封装好了: parallel_for 面向初学者: parallel_for 基于迭代器区间: parallel_for_each 二维区间上的 for 循环: blocked_range2d 三维区间上的 for 循环: blocked_range3d 所有区间类型 第 2 章:缩并与扫描 缩并( reduce ) 1 个线程,依次处理 8 个元素的缩并,花了 ,需要做大量数学运算,因此瓶颈在 ALU 。 • 这里卖个关子,欲知后事如何,请待下集揭晓! 更专业的性能测试框架: Google benchmark • 手动计算时间差有点太硬核了,而且只运 行一次的结果可能不准确,最好是多次运 行取平均值才行。 • 因此可以利用谷歌提供的这个框架。 • 只需将你要测试的代码放在他的 • for (auto _: bm) • 里面即可。他会自动决定要重复多少次,0 码力 | 116 页 | 15.85 MB | 1 年前3
 C++高性能并行编程与优化 -  课件 - 08 CUDA 开启的 GPU 编程示当前编译所针对的 GPU 的架构版本号 是多少。这里是 520 表示版本号是 5.2.0 ,最后一位始终是 0 不用管,我们 通常简称他的版本号为 52 就行了。 • 这个版本号是编译时指定的版本,不是运 行时检测到的版本。编译器默认就是最老 的 52 ,能兼容所有 GTX900 以上显卡。 https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index threadIdx 三维的板块和线程编号 • CUDA 也支持三维的板块和线程区间。 • 只要在三重尖括号内指定的参数改成 dim3 类型即可。 dim3 的构造函数就是接受三 个无符号整数( unsigned int )非常简单 。 • dim3(x, y, z) • 这样在核函数里就可以通过 threadIdx.y 获取 y 方向的线程编号,以此类推。 那二维呢? • 需要二维的话,只需要把 方向有大小,就相当于二维了,不会有 性能损失。实际上一维的 << C++高性能并行编程与优化 -  课件 - 08 CUDA 开启的 GPU 编程示当前编译所针对的 GPU 的架构版本号 是多少。这里是 520 表示版本号是 5.2.0 ,最后一位始终是 0 不用管,我们 通常简称他的版本号为 52 就行了。 • 这个版本号是编译时指定的版本,不是运 行时检测到的版本。编译器默认就是最老 的 52 ,能兼容所有 GTX900 以上显卡。 https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index threadIdx 三维的板块和线程编号 • CUDA 也支持三维的板块和线程区间。 • 只要在三重尖括号内指定的参数改成 dim3 类型即可。 dim3 的构造函数就是接受三 个无符号整数( unsigned int )非常简单 。 • dim3(x, y, z) • 这样在核函数里就可以通过 threadIdx.y 获取 y 方向的线程编号,以此类推。 那二维呢? • 需要二维的话,只需要把 方向有大小,就相当于二维了,不会有 性能损失。实际上一维的 <<- >> 不 过是 << - >> 的简写而已。 图片解释三维的板块和线程 • 之所以会把 blockDim 和 gridDim 分三维主要是因为 GPU 的业务常常涉及到三维图形学和二维图像,觉得 这样很方便,并不一定 GPU 硬件上是三维这样排列 的。 0 码力 | 142 页 | 13.52 MB | 1 年前3
共 24 条
- 1
- 2
- 3













