C++高性能并行编程与优化 - 课件 - 11 现代 CMake 进阶指南现代 CMake 进阶指南 by 彭于斌( @archibate ) 往期录播: https://www.bilibili.com/video/BV1fa411r7zp 课程 PPT 和代码: https://github.com/parallel101/course 为什么要学习现代 CMake ? • 现代 CMake 指的是 CMake 3.x 。 • 古代 CMake 指的是 CMake0 码力 | 166 页 | 6.54 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 16 现代 CMake 模块化项目管理指南现代 CMake 模块化项目管理指南 彭于斌( @archibate ) 课件 & 源码: https://github.com/parallel101/course 往期录播: https://space.bilibili.com/263032155 找不到头文 件怎么办呀 CMake Cookbook 小彭老师建议 : ~~-·~·~-·~ -~·-·~·- 第一章:文件 /0 码力 | 56 页 | 6.87 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程用于定义核函数,他在 GPU 上执行,从 CPU 端通过三重尖括号语法调 用,可以有参数,不可以有返回值。 • 而 __device__ 则用于定义设备函数,他在 GPU 上执行,但是从 GPU 上调用的,而 且不需要三重尖括号,和普通函数用起来一 样,可以有参数,有返回值。 • 即: host 可以调用 global ; global 可以调 用 device ; device 可以调用 device 上的函数。 同时定义在 CPU 和 GPU 上 • 通过 __host__ __device__ 这样的双重修 饰符,可以把函数同时定义在 CPU 和 GPU 上,这样 CPU 和 GPU 都可以调 用。 让 constexpr 函数自动变成 CPU 和 GPU 都可以调用 • 这样相当于把 constexpr 函数自动变成修饰 __host__ __device__ ,从而两边都可以调用。 比如这里设置了 RTX3000 系列的架构版 本号 86 ,在 RTX2080 上就运行不出结 果。 • 最坑的是他不会报错!也不输出任何东西 !就像没有那个 kernel 一样!所以一定 要注意调对你的版本号。否则就会这样 kernel 好像没有执行过一样,只有 CPU 上的代码被执行了。 指定多个版本号 • 可以指定多个版本号,之间用分号分割。 • 运行时可以自动选择最适合当前显卡的版0 码力 | 142 页 | 13.52 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 07 深入浅出访存优化tmp 对象的副本, 防止多线程调用 func 出错。 • 返回时(或者进入时)调用 tmp.clear() 清除已有数据。 由于 vector 的特性,他只会把 size() 标记为 0 并调 用其成员的解构函数,而不会实际释放内存( free )。 • 因此第二次进入的时候,如果 n 不超过上一次的大小 ,就还是用的第一次分配的内存,避免了重新分配的开 销。对 func 需要被重复调用的情况很实用。 了 ,毕竟 16 次加法远远没有超过 membound 的范畴, cpubound 我们已经仁至义尽地尽量 消除了。 • 如果单单采用手动预取,或者单单采用循环分块,那反而还会变慢。这就是性能调优中的一 大难点:某个改动可能对性能没有效果,甚至反而产生负面效果。然而有经验的优化人员会 知道,这不一定意味着这项改动是错的:有可能要配合多个改动一起上,才能有正面效果。 • 性能优化我们需要 blockSize 和 32 似乎一样了, 所以 xBase 也可以直接去掉了。 增加预取的提前量 • 预取的地址太靠近了,可能还是会让 CPU 陷入等待,无法隐藏计算的延迟。 • 再稍微往前调一点点试试看。 • 提前量不能太多,否则需要很大的缓存大 小,否则到时候读的太多又得赶到二级缓 存;也不能太少,否则等计算到那里的时 候数据来不及取出,导致延迟无法隐藏。 性能优化过山车:建议改成现代桃花源记0 码力 | 147 页 | 18.88 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 10 从稀疏数据结构到量化数据类型PPT 和代码: https://github.com/parallel101/course 本课涵盖:稀疏矩阵、 unordered_map 、空间稀 疏网格、位运算、浮点的二进制格式、内存带宽优 化 面向人群:图形学、 CFD 仿真、深度学习编程人 员 第 0 章:稀疏矩阵 稠密数组存储矩阵 用 foreach 包装一下枚举的过程 改用 map 来存储 分离 read/write/create 发现结果不对了……说明 int8_t 太小了(可以容纳 - 128 到 127 ),容纳不下 97*100 这么大的数,发生 了溢出导致结果错误。 试图解决:用 uint8_t 表示,定点数系数调小到 2 • 注意到我们的值始终是正数,因此可以用无符号的 uint8_t (可以容纳 0 到 255 ),然后把刚刚的系数 100 改小到 2 ,成功算对结果了,代价是精度损失了 不少。0 码力 | 102 页 | 9.50 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 03 现代 C++ 进阶:模板元编程• 爱思考:为什么这里 Func 为 4 字节 ? lambda 表达式:如何避免用模板参数 • 虽然这样可以让编译器对 每个不同的 lambda 生成一次,有助于优 化。 • 但是有时候我们希望通过头文件的方式分 离声明和实现,或者想加快编译,这时如 果再用 template class 作为参数就不行了 。 • 为了灵活性,可以用 std::function 语言的 API 比如 pthread 和 atexit 。 lambda + 模板:双倍快乐 • 可以将 lambda 表达式的参数声明为 auto ,声明为 auto 的参数会自动根据调 用者给的参数推导类型,基本上和 template 等价。 • auto const & 也是同理,等价于模板函数 的 T const & 。 • 带 auto 参数的 0 码力 | 82 页 | 12.15 MB | 1 年前3
《深入浅出MFC》2/e或"sleep delay"),再按下 【Resume Thread】。如果你选择¡ §for loop delay¡ ¨(图1-9a),你会看到执行线程0 (优 先权最高)几乎一路冲到底,然后才是执行线程1(优先权次之),然后是执行线程2(优 先权再次之)...。但如果你选择的¡ §sleep delay¡ ¨ (图1-9b),所有执行线程不分优先权高 低,同时行动。关于执行线程的排程问题,我将在第14 成员变量不属于对象的一部份,而是类别的一部份,所以程序可以在还没有诞生任 何对象的时候就处理此种成员变量。但首先你必须初始化它。 不要把static 成员变量的初始化动作安排在类别的构造式中,因为构造式可能一再被调 用,而变量的初值却只应该设定一次。也不要把初始化动作安排在头文件中,因为它可 能会被包含许多地方,因此也就可能被执行许多次。你应该在实作档中且类别以外的任 何位置设定其初值。例如在main 之中,或全域函数中,或任何函数之外: 会做调整,让资料的某一部份显示而某一部份隐藏。 让我做更详细的说明。「GDI 原点」是DC(注)的重要特征,许许多多CDC 成员函 式的绘图结果都会受它的影响。如果我们想在绘图之前(也就是进入OnDraw 之前)调 整DC , 我们可以改写虚拟函数OnPrepareDC , 因为Framework 是先调用 OnPrepareDC,然后才调用OnDraw 并把DC 传进去。好,窗口由无滚动条到增设滚动条的0 码力 | 1009 页 | 11.08 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 04 从汇编角度看编译器优化即可实现同样效 果,就不需要手动写 padding 变量了。 那是不是所有结构体打上 alignas(16) 我的程序就会变快? 错了,有可能不仅不变快,反而还变慢! SIMD 和缓存行对齐只是性能优 化的一个点,又不是全部。还要考虑结构体变大会导致内存带宽的占用, 对缓存的占用等一系列连锁反应,总之,要根据实际情况选择优化方案。 结构体的内存布局: AOS 与 SOA • AOS ( Array0 码力 | 108 页 | 9.47 MB | 1 年前3
Hello 算法 1.0.0b5 C++版对于大顶堆(小顶堆),堆顶元素(即根节点)的值分别是最大(最小)的。 8.1.1 堆常用操作 需要指出的是,许多编程语言提供的是「优先队列 priority queue」,这是一种抽象数据结构,定义为具有优 先级排序的队列。 实际上,堆通常用作实现优先队列,大顶堆相当于元素按从大到小顺序出队的优先队列。从使用角度来看, 我们可以将“优先队列”和“堆”看作等价的数据结构。因此,本书对两者不做特别区分,统一使用“堆“来 285 即便如此,回溯算法仍然是某些搜索问题和约束满足问题的最佳解决方案。对于这些问题,由于无法预测哪 些选择可生成有效的解,因此我们必须对所有可能的选择进行遍历。在这种情况下,关键是如何进行效率优 化,常见的效率优化方法有两种。 ‧ 剪枝:避免搜索那些肯定不会产生解的路径,从而节省时间和空间。 ‧ 启发式搜索:在搜索过程中引入一些策略或者估计值,从而优先搜索最有可能产生有效解的路径。 13 所示,上述方法生成的排列有一半都是重复的。 第 13 章 回溯 hello‑algo.com 289 图 13‑7 重复排列 那么如何去除重复的排列呢?最直接地,考虑借助一个哈希表,直接对排列结果进行去重。然而这样做不够优 雅,因为生成重复排列的搜索分支是没有必要的,应当被提前识别并剪枝,这样可以进一步提升算法效率。 1. 相等元素剪枝 观察图 13‑8 ,在第一轮中,选择 1 或选择 ̂1 是等价的,在这两个选择之下生成的所有排列都是重复的。因此0 码力 | 377 页 | 30.69 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 02 现代 C++ 入门:RAII 内存管理io/) - [C++ 并发编程实战 ](https://www.bookstack.cn/read/Cpp_Concurrency_In_Action/README.md) - [ 因特尔 TBB 编程指南 ](https://www.inf.ed.ac.uk/teaching/courses/ppls/TBBtutorial.pdf) - [ 并行体系结构与编程 (CMU 15-418)](https://www0 码力 | 96 页 | 16.28 MB | 1 年前3
共 20 条
- 1
- 2













