Hello 算法 1.0.0b2 C++版占用内存少、缓存局部性好 占用内存多 优势操作 随机访问 插入、删除 � 缓存局部性的简单解释 在计算机中,数据读写速度排序是“硬盘 < 内存 < CPU 缓存”。当我们访问数组元素时,计算 机不仅会加载它,还会缓存其周围的其它数据,从而借助高速缓存来提升后续操作的执行速度。 链表则不然,计算机只能挨个地缓存各个结点,这样的多次“搬运”降低了整体效率。 ‧ 下表对比了数组与链表的各种操作效率。 然,堆排序一 般无需弹出元素,仅需每轮将堆顶元素交换至数组尾部并减小堆的长度即可。 ‧ 获取最大的 ? 个元素。这既是一道经典算法题目,也是一种常见应用,例如选取热度前 10 的新闻作为 微博热搜,选取前 10 销量的商品等。 8.2. 建堆操作 * 如果我们想要根据输入列表来生成一个堆,这样的操作被称为「建堆」。 8.2.1. 两种建堆方法 借助入堆方法实现 最直接地,考虑借助「 出现最差情况的概率很低:虽然快速排序的最差时间复杂度为 ?(?2) ,不如归并排序,但绝大部分情况 下,快速排序可以达到 ?(? log ?) 的复杂度。 ‧ 缓存使用效率高:哨兵划分操作时,将整个子数组加载入缓存中,访问元素效率很高。而诸如「堆排序」 需要跳跃式访问元素,因此不具有此特性。 ‧ 复杂度的常数系数低:在提及的三种算法中,快速排序的 比较、赋值、交换 三种操作的总体数量最少 (类似于「插入排序」快于「冒泡排序」的原因)。0 码力 | 197 页 | 15.72 MB | 1 年前3
Hello 算法 1.0.0b1 C++版占用内存少、缓存局部性好 占用内存多 优势操作 随机访问 插入、删除 � 缓存局部性的简单解释 在计算机中,数据读写速度排序是“硬盘 < 内存 < CPU 缓存”。当我们访问数组元素时,计算 机不仅会加载它,还会缓存其周围的其它数据,从而借助高速缓存来提升后续操作的执行速度。 链表则不然,计算机只能挨个地缓存各个结点,这样的多次“搬运”降低了整体效率。 ‧ 下表对比了数组与链表的各种操作效率。 然,堆排序一 般无需弹出元素,仅需每轮将堆顶元素交换至数组尾部并减小堆的长度即可。 ‧ 获取最大的 ? 个元素。这既是一道经典算法题目,也是一种常见应用,例如选取热度前 10 的新闻作为 微博热搜,选取前 10 销量的商品等。 8.2. 建堆操作 * 如果我们想要根据输入列表来生成一个堆,这样的操作被称为「建堆」。 8.2.1. 两种建堆方法 借助入堆方法实现 最直接地,考虑借助「 出现最差情况的概率很低:虽然快速排序的最差时间复杂度为 ?(?2) ,不如归并排序,但绝大部分情况 下,快速排序可以达到 ?(? log ?) 的复杂度。 ‧ 缓存使用效率高:哨兵划分操作时,将整个子数组加载入缓存中,访问元素效率很高。而诸如「堆排序」 需要跳跃式访问元素,因此不具有此特性。 ‧ 复杂度的常数系数低:在提及的三种算法中,快速排序的 比较、赋值、交换 三种操作的总体数量最少 (类似于「插入排序」快于「冒泡排序」的原因)。0 码力 | 187 页 | 14.71 MB | 1 年前3
Hello 算法 1.1.0 C++ 版优化数据结构的操作效率。 ‧ 空间效率高:数组为数据分配了连续的内存块,无须额外的结构开销。 ‧ 支持随机访问:数组允许在 ?(1) 时间内访问任何元素。 ‧ 缓存局部性:当访问数组元素时,计算机不仅会加载它,还会缓存其周围的其他数据,从而借助高速缓 存来提升后续操作的执行速度。 连续空间存储是一把双刃剑,其存在以下局限性。 ‧ 插入与删除效率低:当数组中元素较多时,插入与删除操作需要移动大量的元素。 4 章 数组与链表 hello‑algo.com 85 如图 4‑10 所示,在程序运行时,数据会从硬盘中被读取到内存中,供 CPU 计算使用。缓存可以看作 CPU 的 一部分,它通过智能地从内存加载数据,给 CPU 提供高速的数据读取,从而显著提升程序的执行效率,减少 对较慢的内存的依赖。 图 4‑10 硬盘、内存和缓存之间的数据流通 4.4.2 数据结构的内存效率 在内存空间利用方面,数组和链表各自具有优势和局限性。 miss),此时 CPU 不得不从速度较慢的内存中加载所需数据。 显然,“缓存未命中”越少,CPU 读写数据的效率就越高,程序性能也就越好。我们将 CPU 从缓存中成功获 取数据的比例称为缓存命中率(cache hit rate),这个指标通常用来衡量缓存效率。 为了尽可能达到更高的效率,缓存会采取以下数据加载机制。 ‧ 缓存行:缓存不是单个字节地存储与加载数据,而是以缓存行为单位。相比于单个字节的传输,缓存行0 码力 | 379 页 | 18.47 MB | 1 年前3
Hello 算法 1.0.0 C++版优化数据结构的操作效率。 ‧ 空间效率高:数组为数据分配了连续的内存块,无须额外的结构开销。 ‧ 支持随机访问:数组允许在 ?(1) 时间内访问任何元素。 ‧ 缓存局部性:当访问数组元素时,计算机不仅会加载它,还会缓存其周围的其他数据,从而借助高速缓 存来提升后续操作的执行速度。 连续空间存储是一把双刃剑,其存在以下局限性。 ‧ 插入与删除效率低:当数组中元素较多时,插入与删除操作需要移动大量的元素。 4 章 数组与链表 hello‑algo.com 85 如图 4‑10 所示,在程序运行时,数据会从硬盘中被读取到内存中,供 CPU 计算使用。缓存可以看作 CPU 的 一部分,它通过智能地从内存加载数据,给 CPU 提供高速的数据读取,从而显著提升程序的执行效率,减少 对较慢的内存的依赖。 图 4‑10 硬盘、内存和缓存之间的数据流通 4.4.2 数据结构的内存效率 在内存空间利用方面,数组和链表各自具有优势和局限性。 miss」,此时 CPU 不得不从速度较慢的内存中加载所需数据。 显然,“缓存未命中”越少,CPU 读写数据的效率就越高,程序性能也就越好。我们将 CPU 从缓存中成功获 取数据的比例称为「缓存命中率 cache hit rate」,这个指标通常用来衡量缓存效率。 为了尽可能达到更高的效率,缓存会采取以下数据加载机制。 ‧ 缓存行:缓存不是单个字节地存储与加载数据,而是以缓存行为单位。相比于单个字节的传输,缓存行0 码力 | 378 页 | 17.59 MB | 1 年前3
Hello 算法 1.2.0 简体中文 C++ 版优化数据结构的操作效率。 ‧ 空间效率高:数组为数据分配了连续的内存块,无须额外的结构开销。 ‧ 支持随机访问:数组允许在 ?(1) 时间内访问任何元素。 ‧ 缓存局部性:当访问数组元素时,计算机不仅会加载它,还会缓存其周围的其他数据,从而借助高速缓 存来提升后续操作的执行速度。 连续空间存储是一把双刃剑,其存在以下局限性。 ‧ 插入与删除效率低:当数组中元素较多时,插入与删除操作需要移动大量的元素。 数组与链表 www.hello‑algo.com 85 如图 4‑10 所示,在程序运行时,数据会从硬盘中被读取到内存中,供 CPU 计算使用。缓存可以看作 CPU 的 一部分,它通过智能地从内存加载数据,给 CPU 提供高速的数据读取,从而显著提升程序的执行效率,减少 对较慢的内存的依赖。 图 4‑10 硬盘、内存和缓存之间的数据流通 4.4.2 数据结构的内存效率 在内存空间利用方面,数组和链表各自具有优势和局限性。 miss),此时 CPU 不得不从速度较慢的内存中加载所需数据。 显然,“缓存未命中”越少,CPU 读写数据的效率就越高,程序性能也就越好。我们将 CPU 从缓存中成功获 取数据的比例称为缓存命中率(cache hit rate),这个指标通常用来衡量缓存效率。 为了尽可能达到更高的效率,缓存会采取以下数据加载机制。 ‧ 缓存行:缓存不是单个字节地存储与加载数据,而是以缓存行为单位。相比于单个字节的传输,缓存行0 码力 | 379 页 | 18.48 MB | 10 月前3
Hello 算法 1.0.0b4 C++版(?) 添加元素 ?(?) ?(1) 删除元素 ?(?) ?(1) � 缓存局部性 在计算机中,数据读写速度排序是“硬盘 < 内存 < CPU 缓存”。当我们访问数组元素时,计算 机不仅会加载它,还会缓存其周围的其他数据,从而借助高速缓存来提升后续操作的执行速 度。链表则不然,计算机只能挨个地缓存各个节点,这样的多次“搬运”降低了整体效率。 4.4.1. Q & A � 数组存储 数 据。然而,我们通常会使用一种更优雅的方式实现堆排序,详见后续的堆排序章节。 ‧ 获取最大的 ? 个元素:这是一个经典的算法问题,同时也是一种典型应用,例如选择热度前 10 的新闻 作为微博热搜,选取销量前 10 的商品等。 8.2. 建堆操作 如果我们想要根据输入列表生成一个堆,这个过程被称为「建堆」。 8.2.1. 借助入堆方法实现 最直接的方法是借助“元素入堆操作”实现,首先 出现最差情况的概率很低:虽然快速排序的最差时间复杂度为 ?(?2) ,没有归并排序稳定,但在绝大 多数情况下,快速排序能在 ?(? log ?) 的时间复杂度下运行。 ‧ 缓存使用效率高:在执行哨兵划分操作时,系统可将整个子数组加载到缓存,因此访问元素的效率较 高。而像「堆排序」这类算法需要跳跃式访问元素,从而缺乏这一特性。 ‧ 复杂度的常数系数低:在上述三种算法中,快速排序的比较、赋值、交换等操作的总数量最少。这与 「0 码力 | 343 页 | 27.39 MB | 1 年前3
Hello 算法 1.0.0b5 C++版优化数据结构的操作效率。 ‧ 空间效率高: 数组为数据分配了连续的内存块,无须额外的结构开销。 ‧ 支持随机访问: 数组允许在 ?(1) 时间内访问任何元素。 ‧ 缓存局部性: 当访问数组元素时,计算机不仅会加载它,还会缓存其周围的其他数据,从而借助高速缓 存来提升后续操作的执行速度。 连续空间存储是一把双刃剑,其存在以下缺点。 ‧ 插入与删除效率低: 当数组中元素较多时,插入与删除操作需要移动大量的元素。 数 据。然而,我们通常会使用一种更优雅的方式实现堆排序,详见后续的堆排序章节。 ‧ 获取最大的 ? 个元素:这是一个经典的算法问题,同时也是一种典型应用,例如选择热度前 10 的新闻 作为微博热搜,选取销量前 10 的商品等。 8.2 建堆操作 在某些情况下,我们希望使用一个列表的所有元素来构建一个堆,这个过程被称为“建堆操作”。 8.2.1 自上而下构建 我们首先创建一个空堆,然后 出现最差情况的概率很低:虽然快速排序的最差时间复杂度为 ?(?2) ,没有归并排序稳定,但在绝大 多数情况下,快速排序能在 ?(? log ?) 的时间复杂度下运行。 ‧ 缓存使用效率高:在执行哨兵划分操作时,系统可将整个子数组加载到缓存,因此访问元素的效率较 高。而像“堆排序”这类算法需要跳跃式访问元素,从而缺乏这一特性。 ‧ 复杂度的常数系数低:在上述三种算法中,快速排序的比较、赋值、交换等操作的总数量最少。这与 “0 码力 | 377 页 | 30.69 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 性能优化之无分支编程 Branchless Programming因此对于简单的分支,完全可以不考虑优化, 交给编译器自动优化掉。 • 一般只需要把 if-else 改成三目运算符 ?: 编 译器就能成功识别了(见开头的例子)。 • 建议只有当性能遇到瓶颈时,再去针对性对 “热代码”优化,而不是一股脑儿全部改成无分 支,影响可读性。 “ 妙用加减乘”的无分支优化是万能的吗? • return x >= 0 ? sqrt(x) : 0; • 能不能优化成: • return 取这个地址。 • 例如:定义一个函数指针 void (*func)(int x); 则对他的调用 (*func)(42); 会得到: • mov edi, 42 • call [func] 热知识: C++ 的虚函数就是函数指针 • 通过 virtual 关键字给类定义一个虚函数,他其实就是在类成员里加了一个函数指针。 • 而在构造函数里,会把当前类重载过的虚函数,赋予给那个函数指针,实现多态。0 码力 | 47 页 | 8.45 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 01 学 C++ 从 CMake 学起积变大,但是只需要 一个文件即可运行。 • 而动态库则只在生成的可执行文件中生成“插桩”函数,当可执行文件被加载时会读取指定目 录中的 .dll 文件,加载到内存中空闲的位置,并且替换相应的“插桩”指向的地址为加载后的 地址,这个过程称为重定向。这样以后函数被调用就会跳转到动态加载的地址去。 • Windows :可执行文件同目录,其次是环境变量 %PATH% • Linux : ELF0 码力 | 32 页 | 11.40 MB | 1 年前3
《深入浅出MFC》2/eDLL)提供(注)。虽说动态联结是在执行时期才发生「联 6 结」事实,但在联结时期,联结器仍需先为调用者(应用程序本身)准备一些适当的信 息,才能够在执行时期顺利「跳」到DLL 执行。如果该API 所属之函数库尚未加载, 系统也才因此知道要先行加载该函数库。这些适当的信息放在所谓的「import 函数库」 中。32 位Windows 的三大模块所对应的import 函数库分别为GDI32.LIB 和USER32.LIB 和KERNEL32 和_cdecl 当Windows 的「外壳」(shell,例如Windows 3.1 的程序管理员或Windows 95 的文件 总管)侦测到使用者意欲执行一个Windows 程序,于是调用加载器把该程序加载,然后 调用C startup code,后者再调用WinMain,开始执进程序。WinMain 的四个参数由操作 系统传递进来。 16 窗口类别之注册与窗口之诞生 一开始,Windows 调用CreateProcess 激活App.exe。 2. 系统产生一个「进程核心对象」,计数值为1。 3. 系统为此进程建立一个4GB 地址空间。 4. 加载器将必要的码加载到上述地址空间中,包括App.exe 的程序、资料,以及 所需的动态联结函数库(DLLs)。加载器如何知道要加载哪些DLLs 呢?它 们被记录在可执行文件(PE 文件格式)的.idata section 中。 5. 系统为此进程建立一个执行线程,称为主执行线程(primary0 码力 | 1009 页 | 11.08 MB | 1 年前3
共 15 条
- 1
- 2













