C++高性能并行编程与优化 - 课件 - 04 从汇编角度看编译器优化
从汇编角度看编译器优化 by 彭于斌( @archibate ) 往期录播: https://www.bilibili.com/video/BV1fa411r7zp 课程 PPT 和代码: https://github.com/parallel101/course 高性能并行编程与优化 - 课程大纲 • 分为前半段和后半段,前半段主要介绍现代 C++ ,后半段主要介绍并行编程与优化。 1 1.课程安排与开发环境搭建: cmake 与 git 入门 2.现代 C++ 入门:常用 STL 容器, RAII 内存管理 3.现代 C++ 进阶:模板元编程与函数式编程 4.编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 cpu 缓存机制 x64 架构下的寄存器模型 通用寄存器: 32 位时代 • 32 位 x86 架构中的通用寄存器有: • eax, ecx, edx, ebx, esi, edi, esp, ebp • 其中 esp 是堆栈指针寄存器,和函数的调用与返回相关。 • 其中 eax 是用于保存返回值的寄存器。 通用寄存器: 64 位时代 • 64 位 x86 架构中的通用寄存器有: • rax, rcx0 码力 | 108 页 | 9.47 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 14 C++ 标准库系列课 - 你所不知道的 set 容器
set 容 器 by 小彭老师( @archibate ) 课件 & 代码: https://github.com/parallel101/course 上期回顾: https://www.bilibili.com/video/BV1qF411T7sd 课程安排 1. vector 容器初体验 & 迭代器入门 (BV1qF411T7sd) 2. 你所不知道的 set 容器 & 迭代器分类 ( 容器全家桶及其妙用举例 5. 函子 functor 与 lambda 表达式知多少 6. 通过实战案例来学习 STL 算法库 7. C++ 标准输入输出流 & 字符串格式化 8. traits 技术,用户自定义迭代器与算法 9. allocator ,内存管理与对象生命周期 set 和 vector 的区别 • 都是能存储一连串数据的容器 。 • 区别 1 : set 会自动给其中的 元素从小到大排序,而 vector 迭代器的共同点 • 上节课讲了迭代器: vector 具 有 begin() 和 end() 两个成 员函数,他们分别返回指向数 组头部元素和尾部再之后一格 元素的迭代器对象。 • vector 作为连续数组,他的迭 代器基本等效于指针。 • set 也有 begin() 和 end() 函数,他返回的迭代器对象重 载了 * 来访问指向的地址。 迭代器的五大分类 提供的运算符重载0 码力 | 83 页 | 10.23 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 13 C++ STL 容器全解之 vector
com/video/BV1fa411r7zp 课程 PPT 和代码: https://github.com/parallel101/course C++ 标准库五大件:容器( container ) C++ 标准库五大件:迭代器( iterator ) C++ 标准库五大件:算法( algorithm ) C++ 标准库五大件:仿函数( functor ) C++ 标准库五大件:分配器( allocator ) 侯捷 函数会检测索引 i 是否越界,如果他 发现索引 i >= a.size() 则会抛出异常 std::out_of_range 让程序提前终止(或者被 try-catch 捕获),配合任意一款调试器,就可 以很快速地定位到出错点。 • 不过 at 需要额外检测下标是否越界,虽然更安 全方便调试,但和 [] 相比有一定性能损失。 • int &at(size_t i); • int const 脱离作用域会释放的 麻烦,让 lambda 中仍可访问对象。 • 至于那个全局变量本身有没有被使用则无所谓 (我们是通过首地址指针间接访问)。他的存 在只是为了延续生命周期,告知 C++ 编译器 什么时候能 delete 而已。 (注: C++ 规定全局变量都会在进入 main 函数之前构造, main 函数返回之后解构) vector 容器: resize 到更大尺寸会导致 data0 码力 | 90 页 | 4.93 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 17 由浅入深学习 map 容器
能不能在遍历的同时删除元素?安全吗? emplace , emplace_hint , try_emplace 的区别? 课程安排 1. vector 容器初体验 & 迭代器入门 (BV1qF411T7sd) 2. 你所不知道的 set 容器 & 迭代器分类 (BV1m34y157wb) 3. string , string_view , const char * 的爱恨纠葛 (BV1ja411M7Di) 4 本期 ) 5. 函子 functor 与 lambda 表达式知多少 6. 通过实战案例来学习 STL 算法库 7. C++ 标准输入输出流 & 字符串格式化 8. traits 技术,用户自定义迭代器与算法 9. allocator ,内存管理与对象生命周期 10. C++ 异常处理机制的前世今生 我们都要认真鞋习哦 我们都要认真鞋习哦 第一章:读取与写入 我负责监督你鞋习 ! 我负责监督你鞋习 insert_or_assign(key, val) 不覆盖写入,要用 m.insert({key, val}) 判断是否存在,用 m.count(key) 若存在则删除,用 m.erase(key) 第四章:迭代与遍历 物理格式 逻辑格式 面壁者罗辑监督你鞋习 ! 面壁者罗辑监督你鞋习 ! map 的元素类型是…… • set::value_type 是 V 。 • map ::value_type 0 码力 | 90 页 | 8.76 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅
,后半段主要介绍并行编程与优化。 1.课程安排与开发环境搭建: cmake 与 git 入门 2.现代 C++ 入门:常用 STL 容器, RAII 内存管理 3.现代 C++ 进阶:模板元编程与函数式编程 4.编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 cpu 2.x (作业上传到 GitHub ) CUDA Toolkit 10.0 以上( GPU 专题) 第 0 章:从并发到并行 摩尔定律:停止增长了吗? • 晶体管的密度的确仍在指数增长,但处理器主 频却开始停止增长了,甚至有所下降。 • 很长时间之前我们就可以达到 2GHz ( 2001 年 8 月),根据 2003 年的趋势,在 2005 年 初我们就应该研发出 10GHz 的芯片。 3GHz < 6GHz • 一个由双核组成的 3GHz 的 CPU 实际上提供了 6GHz 的处理能力,是吗? • 显然不是。甚至在两个处理器上同时运行两个线程也不见得可以获得两倍的性能。相似的 ,大多数多线程的应用不会比双核处理器的两倍快。他们应该比单核处理器运行的快,但 是性能毕竟不是线性增长。 • 为什么无法做到呢?首先,为了保证缓存一致性以及其他握手协议需要运行时间开销。在 今天,双核0 码力 | 116 页 | 15.85 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程
文件,和 .cpp 一样。 https://www.nvidia.cn/docs/IO/51635/NVIDIA_CUDA_Programming_Guide_1.1_chs.pdf CUDA 编译器兼容 C++17 • CUDA 的语法,基本完全兼容 C++ 。包括 C+ +17 新特性,都可以用。甚至可以把任何一个 C++ 项目的文件后缀名全部改成 .cu ,都能编 译出来。 • 这是 里去。 • 因此 CUDA 编译器提供了一个“私货”关键字: __inline__ 来 声明一个函数为内联。不论是 CPU 函数还是 GPU 都可以使 用,只要你用的 CUDA 编译器。 GCC 编译器相应的私货则 是 __attribute__((“inline”)) 。 • 注意声明为 __inline__ 不一定就保证内联了,如果函数太大编 译器可能会放弃内联化。因此 CUDA 还提供 #ifdef 指令针对 CPU 和 GPU 生成不同的代码 • CUDA 编译器具有多段编译的特点。 • 一段代码他会先送到 CPU 上的编译器(通常是系统自带的编译 器比如 gcc 和 msvc )生成 CPU 部分的指令码。然后送到真 正的 GPU 编译器生成 GPU 指令码。最后再链接成同一个文件 ,看起来好像只编译了一次一样,实际上你的代码会被预处理很 多次。 • 他在 GPU 编译模式下会定义0 码力 | 142 页 | 13.52 MB | 1 年前3现代C++ 教程:高速上手C++11/14/17/20
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 区间 for 迭代 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.5 模板 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.2 函数对象包装器 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 std::function 本书每章最后还加入了少量难度极小的习题,仅用于检验你是否能混合运用当前章节中的知识点。你 可以在这里找到习题的答案,文件夹名称为章节序号。 第 1 章迈向现代 C++ 编译环境:本书将使用 clang++ 作为唯一使用的编译器,同时总是在代码中使用 -std=c++2a 编译 标志。 > clang++ -v Apple LLVM version 10.0.1 (clang-1001.0.46.4) Target:0 码力 | 83 页 | 2.42 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 07 深入浅出访存优化
。 • 因此,对 fill 这种没有任何计算量,纯粹只有访存的循环体,并 行没有加速效果。称为内存瓶颈( memory-bound )。 • 而 sine 这种内部需要泰勒展开来计算,每次迭代计算量很大的 循环体,并行才有较好的加速效果。称为计算瓶颈( cpu- bound )。 • 并行能减轻计算瓶颈,但不减轻内存瓶颈,故后者是优化的重点 。 浮点加法的计算量 • 冷知识: 。 • 这是为什么? CPU 内部的高速缓存 • 原来 CPU 的厂商早就意识到了内存延迟高,读写效率低 下的问题。因此他们在 CPU 内部引入了一片极小的存储 器——虽然小,但是读写速度却特别快。这片小而快的 存储器称为缓存( cache )。 • 当 CPU 访问某个地址时,会先查找缓存中是否有对应的 数据。如果没有,则从内存中读取,并存储到缓存中; 如果有,则直接使用缓存中的数据。 需要注意, stream 系列指令写入的地址 ,必须是连续的,中间不能有跨步,否则 无法合并写入,会产生有中间数据读的带 宽。 写入 1 比写入 0 更慢? • 很简单,因为写入 0 被编译器自动优化成 了 memset ,而 memset 内部利用了 stream 指令得以更快写入。 写入 1 比写入 0 更慢?解决 • 解决办法就是,我们也用 stream 指令, 这样就可以和标准库优化过的0 码力 | 147 页 | 18.88 MB | 1 年前3Hello 算法 1.1.0 C++ 版
17 2.1 算法效率评估 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.2 迭代与递归 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.3 时间复杂度 . . 一方面,难以排除测试环境的干扰因素。硬件配置会影响算法的性能。比如在某台计算机中,算法 A 的运行 时间比算法 B 短;但在另一台配置不同的计算机中,可能得到相反的测试结果。这意味着我们需要在各种机 器上进行测试,统计平均效率,而这是不现实的。 另一方面,展开完整测试非常耗费资源。随着输入数据量的变化,算法会表现出不同的效率。例如,在输入 数据量较小时,算法 A 的运行时间比算法 B 短;而在输 解,以便能够完成简单算 法的复杂度分析。 2.2 迭代与递归 在算法中,重复执行某个任务是很常见的,它与复杂度分析息息相关。因此,在介绍时间复杂度和空间复杂 度之前,我们先来了解如何在程序中实现重复执行任务,即两种基本的程序控制结构:迭代、递归。 2.2.1 迭代 迭代(iteration)是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某段 代码,直到这个条件不再满足。0 码力 | 379 页 | 18.47 MB | 1 年前3Hello 算法 1.0.0 C++版
17 2.1 算法效率评估 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.2 迭代与递归 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.3 时间复杂度 . . 一方面,难以排除测试环境的干扰因素。硬件配置会影响算法的性能。比如在某台计算机中,算法 A 的运行 时间比算法 B 短;但在另一台配置不同的计算机中,可能得到相反的测试结果。这意味着我们需要在各种机 器上进行测试,统计平均效率,而这是不现实的。 另一方面,展开完整测试非常耗费资源。随着输入数据量的变化,算法会表现出不同的效率。例如,在输入 数据量较小时,算法 A 的运行时间比算法 B 短;而在输 解,以便能够完成简单算 法的复杂度分析。 2.2 迭代与递归 在算法中,重复执行某个任务是很常见的,它与复杂度分析息息相关。因此,在介绍时间复杂度和空间复杂 度之前,我们先来了解如何在程序中实现重复执行任务,即两种基本的程序控制结构:迭代、递归。 2.2.1 迭代 「迭代 iteration」是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某 段代码,直到这个条件不再满足。0 码力 | 378 页 | 17.59 MB | 1 年前3
共 32 条
- 1
- 2
- 3
- 4