C++高性能并行编程与优化 - 课件 - 12 从计算机组成原理看 C 语言指针
的但是大小相等,则结果是 unsigned 的。 • unsigned int + int = unsigned int • 只有两边都是有符号的 int 时,结果才是有符号的 int 。 浮点与标准库数学函数 浮点数的二进制表示 • float 由 4 个字节组成,也就是 32 个位。 • 最高位是符号位,接着的 8 位是指数位 (e) 。 • 剩下的 23 位是底数位 (m) 。 • 值得注意的是指数位 ,作为牛顿 迭代的初始猜测值而已。看他的 i >> 1 这 里,就是把指数和底数都移动了 1 (因为 符号始终是无符号,底数影响不大)。 abs 函数:取出绝对值 • 可以用 abs 这个函数取出一个整数的绝对值 。 abs 函数:取出绝对值 • 如果用来获取 float 类型的绝对值呢? • 编译通过了,但是结果却不对! • 你会发现 x 无论如何变化,都是 0.0 。 • printf 的错误:不会编译时检测参数类型是否正确 • 第一个 bug 是, printf 其实不知道他的参数是什 么类型,他只看到你字符串里写的 “ %f” ,会误以 为输入的是 float 参数。 • 如果你输入的是 3 这样的 int 类型常量, C 语 言不会帮你检测到他和 “ %f” 其实是不匹配的,而 是直接把 int 类型的 4 个字节推到栈上作为 printf 的参数,而0 码力 | 128 页 | 2.95 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 15 C++ 系列课:字符与字符串
万能的 map 容器全家桶及其妙用举例 5. 函子 functor 与 lambda 表达式知多少 6. 通过实战案例来学习 STL 算法库 7. C++ 标准输入输出流 & 字符串格式化 8. traits 技术,用户自定义迭代器与算法 9. allocator ,内存管理与对象生命周期 ASCII 码 第 1 章 计算机如何表达字符 https://zh 程序收到 ^C 以后,就直接终止退 出了。 关于控制字符的一个冷知识 • 除此之外,因为 ^D 是“传输终止符”,还可以在控制 台输入 Ctrl+D 来关闭标准输入流,终止正在读取他 的程序。 • 小彭老师常用 Ctrl+D 来快速关闭一个 shell (和输入 exit 命令的效果一样)。 • 以及按 Ctrl+I 的效果其实和 Tab 键一样,按 Ctrl+J 的效果和 Enter 键一样,按 就是 ‘ \b’ ,所以以前原始的计算机键盘上其 实还没有 Enter 键,大家都是按 Ctrl+J 来换行的… … • 不过,如果直接在控制台输入 ‘ ^’ 和 ‘ C’ 两个字符并 没有 Ctrl+C 的效果哦!因为 ‘ ^C’ 是 Ctrl+C 输入之 后一次性显示出来的,并不是真的说 Ctrl 就是 ‘ ^’ 这 个字符。 C 语言字符串 第 2 章 C 语言中的字符类型 char0 码力 | 162 页 | 40.20 MB | 1 年前3C++高性能并行编程与优化 - 课件 - Zeno 中的现代 C++ 最佳实践
INode 一切节点的公共基类。 多态的经典案例 • IObject 具有一个 eatFood 纯虚函数,而 CatObject 和 DogObject 继承自 IObject ,他 们实现了 eatFood 这个虚函数,实现了多态。 • 注意这里解构函数( ~IObject )也需要是虚函数 ,否则以 IObject * 存储的指针在 delete 时只 会释放 IObject 里的成员,而不会释放 m_catFood 。所以 这里的解构函数也是多态的,他根据类型的不同 调用不同派生类的解构函数。 多态用于设计模式之“模板模式” • 这样之后如果有一个任务是要基于 eatFood 做文章,比如要重复 eatFood 两遍。 • 就可以封装到一个函数 eatTwice 里,这个函数只需接受他们共同的基类 IObject 作为参数,然后调 用 eatFood 这个虚函数来做事(而不是直接操作具体的猫和狗本身)。 dont-repeat-yourself ), 也让函数的作者不必去关注点从猫和狗的其他具体细节,只需把握住他们统一具有的“吃”这个接口。 小知识: shared_ptr 如何深拷贝? 浅拷贝: 深拷贝: 思考:能不能把拷贝构造函数也作为虚函数? • 现在我们的需求有变,不是去对同一个对象调用两次 eatTwice ,而是先把对象复制一份 拷贝,然后对对象本身和他的拷贝都调用一次 eatFood 虚函数。 • 代码如下0 码力 | 54 页 | 3.94 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 14 C++ 标准库系列课 - 你所不知道的 set 容器
const char * 的爱恨纠葛 4. 万能的 map 容器全家桶及其妙用举例 5. 函子 functor 与 lambda 表达式知多少 6. 通过实战案例来学习 STL 算法库 7. C++ 标准输入输出流 & 字符串格式化 8. traits 技术,用户自定义迭代器与算法 9. allocator ,内存管理与对象生命周期 set 和 vector 的区别 • 都是能存储一连串数据的容器 这样只会按字符串指针的地址去判断相等, 而不是所指向字符串的内容。 set 的排序:自定义排序函数 • set 作为模板类,其实有两 个模板参数: set• 第一个 T 是容器内元素的类 型,例如 int 或 string 等。 • 第二个 CompT 定义了你想 要的比较函子, set 内部会 调用这个函数来决定怎么排 序。 • 如果 CompT 不指定,默认 会直接用运算符 化。 set 的排序:自定义排序函数 • 恶搞一下,这里我们把比较 函子 MyComp 定义成只比 较字符串第一个字符 a[0] < b[0] 。 • 神奇的一幕发生了,“ any” 不见了!为什么?因为去重 ! • 为什么 set 会把 “ arch” 和 “ any” 视为相等的元素?明 明内容都不一样? set 的排序:自定义排序函数 • 首先搞懂 set 内部是怎么确定 0 码力 | 83 页 | 10.23 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.被忽视的访存优化:内存带宽与 for (auto _: bm) • 里面即可。他会自动决定要重复多少次, 保证结果是准确的,同时不浪费太多时间 。 运行结果 刚才的 BENCHMARK_MAIN 自动生成了一个 main 函数 ,从而生成一个可执行文件供你运行。运行后会得到测试 的结果打印在终端上。 命令行参数 他还接受一些命令行参数来控制测试的输出格式为 csv 等等,你可以调用 --help 查看更多用法。 CMake 2 3 4 解决 3 :每个线程一个任务队列,做完本职工作后可以认领其他线程的任务 工作窃取法( work-stealing ) 原始的单一任务队列 解决 4 :随机分配法(通过哈希函数或线性函数) • 然而队列的实现较复杂且需要同步机制,还是有一 定的 overhead ,因此另一种神奇的解法是: • 我们仍是分配 4 个线程,但还是把图像切分为 16 份。然后规定每一份按照 xy0 码力 | 116 页 | 15.85 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 01 学 C++ 从 CMake 学起
,后半段主要介绍并行编程与优化。 1.课程安排与开发环境搭建: cmake 与 git 入门 2.现代 C++ 入门:常用 STL 容器, RAII 内存管理 3.现代 C++ 进阶:模板元编程与函数式编程 4.编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 标准生成相应的机器指令码,输出到 a.out 这个文件中,(称为可执行文件)。 • > ./a.out • 之后执行该命令,操作系统会读取刚刚生成的可执行文件,从而执行其中编译成机器码, 调用系统提供的 printf 函数,并在终端显示出 Hello, world 。 厂商 C C++ Fortran GNU gcc g++ gfortran LLVM clang clang++ flang 多文件编译与链接 可以自动检测源文件和头文件之间的依赖关系,导出到 Makefile 里。 • make 的语法非常简单,不像 shell 或 python 可以做很多判断等。 • CMake 具有相对高级的语法,内置的函数能够处理 configure , install 等常见需求。 • 不同的编译器有不同的 flag 规则,为 g++ 准备的参数可能对 MSVC 不适用。 • CMake 可以自动检测当前的编译器,需要添加哪些0 码力 | 32 页 | 11.40 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 05 C++11 开始的多线程编程
,后半段主要介绍并行编程与优化。 1.课程安排与开发环境搭建: cmake 与 git 入门 2.现代 C++ 入门:常用 STL 容器, RAII 内存管理 3.现代 C++ 进阶:模板元编程与函数式编程 4.编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 现代 C++ 中的多线程: std::thread • C++11 开始,为多线程提供了语言级别的 支持。他用 std::thread 这个类来表示线 程。 • std::thread 构造函数的参数可以是任意 lambda 表达式。 • 当那个线程启动时,就会执行这个 lambda 里的内容。 • 这样就可以一边和用户交互,一边在另一 个线程里慢吞吞下载文件了。 错误:找不到符号 过程中也可以响应用户请求,提升了体验 。 • 可是发现一个问题:我输入完 pyb 以后, 他的确及时地和我交互了。但是用户交互 所在的主线程退出后,文件下载所在的子 线程,因为从属于这个主线程,也被迫退 出了。 主线程等待子线程结束: t1.join() • 因此,我们想要让主线程不要急着退出, 等子线程也结束了再退出。 • 可以用 std::thread 类的成员函数 join() 来等待该进程结束。0 码力 | 79 页 | 14.11 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 09 CUDA C++ 流体仿真实战
要访问一个多维数组,必须先创建一个表面对象 ( cudaSurfaceObject_t )。 • 考虑到多维数组始终是需要通过表面对象来访问的,这 里我们让表面对象继承自多维数组。 • 在核函数中可以用 surf3Dread 和 surf3Dwrite 来读写 表面对象中的元素, x,y,z 参数指定要访问元素的坐标 ,要注意 x 必须乘以 sizeof( 元素类型 ) ,否则出错。 表面对象访问数组是可读可写的。纹理对象也可以访问 数组,不过是只读的。好处是他可以通过浮点坐标来访 问,且提供了线性滤波的能力。 • 在核函数中可以通过 tex3D 来读取纹理中的值。 • 之所以纹理是因为 GPU 一开始是渲染图形的专用硬件 ,会用到一些贴图等,这就是二维的纹理。 • 当输入的浮点坐标不是整数时,由 GPU 硬件提供双线 性插值( bilerp ),比手写的高效许多。 • 当然如果是三维数组,那就是三维纹理对象,访问时是 和 resample_kernel 。 • 首先通过 advect_kernel 算出对流后要采样的位置,写入到 loc 。然后再对 clr 和 vel 分别从 loc 算出的位置重 新采样。核函数的 gridDim 通过上整除技巧保证每个元素都能访问到, blockDim 为 8x8x8=512 。 • 如果在 resample_kernel 需要读取 clr ,然后再写入 clr ,并且读写是不同的坐标位置。0 码力 | 58 页 | 14.90 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 17 由浅入深学习 map 容器
(BV1ja411M7Di) 4. 万能的 map 容器全家桶及其妙用举例 ( 本期 ) 5. 函子 functor 与 lambda 表达式知多少 6. 通过实战案例来学习 STL 算法库 7. C++ 标准输入输出流 & 字符串格式化 8. traits 技术,用户自定义迭代器与算法 9. allocator ,内存管理与对象生命周期 10. C++ 异常处理机制的前世今生 我们都要认真鞋习哦 我们都要认真鞋习哦 m.at(“key”) = val; // 写入键值为 “ key” 的元素,如果不存在,抛出异常 • 毕竟 [] 和 at() 只是返回引用,不管你是读取还是写入这个引用,函数本身的特性是不变的。 • 唯一的区别是等号在他后面,是往 K 对应的 V 里赋值。 • [] 创建在先, = 写入在后。成功写入了新建的元素。 • at 报错在先, = 写入在后。结果是报错了,没有写入。 写入用 [] • 很多同学会困惑,为什么要设计两套, C++ 他爸是精神分裂症吗? • 恰恰相反, C++ 是中两个函数不论读写都一视同仁: at 总是抛出异常, [] 总是默默创建 。 • 这么看 Python 才是精分:同一个 [] 函数在读取的时候抛出异常,写入的时候又默默创建 。 • 例如:一个同学问小彭老师在干嘛? • 小彭老师说“我在吃答辩。”那么同学认为这0 码力 | 90 页 | 8.76 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 02 现代 C++ 入门:RAII 内存管理
,后半段主要介绍并行编程与优化。 1.课程安排与开发环境搭建: cmake 与 git 入门 2.现代 C++ 入门:常用 STL 容器, RAII 内存管理 3.现代 C++ 进阶:模板元编程与函数式编程 4.编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: OpenMP 与 Intel TBB 7.被忽视的访存优化:内存带宽与 zhihu.com/p/350068132 未来: C++20 引入模块( module ) https://zhuanlan.zhihu.com/p/350136757 未来: C++20 允许函数参数为自动推断( auto ) 未来: C++20 引入协程( coroutine )和生成器( generator ) 未来: C++20 标准库加入 format 支持 跑远了! • 鉴于 这种情况出现时,就意味着你需要把成员变量的读写封装为成员函数 不变性:请勿滥用封装 • 仅当出现“修改一个成员时,其他也成员要 被修改,否则出错”的现象时,才需要 getter/setter 封装。 • 各个成员之间相互正交,比如数学矢量类 Vec3 ,就没必要去搞封装,只会让程序员 变得痛苦,同时还有一定性能损失:特别 是如果 getter/setter 函数分离了声明和定 义,实现在另一个文件时!0 码力 | 96 页 | 16.28 MB | 1 年前3
共 25 条
- 1
- 2
- 3