C++高性能并行编程与优化 - 课件 - 14 C++ 标准库系列课 - 你所不知道的 set 容器
会把重复的元素 去除,只保留一个,即去重。 • 区别 3 : vector 中的元素在内 存中是连续的,可以高效地按 索引随机访问, set 则不行。 • 区别 4 : set 中的元素可以高 效地按值查找,而 vector 则 低效。 set 的排序: string 会按“字典序”来排 • set 会从小到大排序,对 int 来 说就是数值的大小比较。那么对 字符串类型 string 要怎么排序 复的元素,但仍保留自动排 序,能高效地查询的特点。 • 特点:因为 multiset 不会去 重,但又自动排序,所以其 中所有相等的元素都会紧挨 着,例如 {1, 2, 2, 4, 6} 。 查找 multiset 中的等值区间 • 刚刚说了 multiset 里相等的 元素都是紧挨着排列的。 • 所以可以用 upper_bound 和 lower_bound 函数获取 所有相等值的区间。 upper_bound(2) 查找 multiset 中的等值区间 • 对于 lower_bound 和 upper_bound 的参数相同的 情况,可以用 equal_range 一次性求出两个边界,获得 等值区间,更高效。 • pairequal_range(int const &val) const; 查找 multiset 中的等值区间 0 码力 | 83 页 | 10.23 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 17 由浅入深学习 map 容器
,内存管理与对象生命周期 10. C++ 异常处理机制的前世今生 我们都要认真鞋习哦 我们都要认真鞋习哦 第一章:读取与写入 我负责监督你鞋习 ! 我负责监督你鞋习 ! map 查找元素的两个接口 • map 提供了两个查找元素的接口,一曰 [] ,二曰 at 。 • 那么他们两个又有什么区别呢?很多新手都分不清他俩,可能只认识 [] 。 读取 map 元素 • mapmap 的元素类型是…… • pair 。 • 可是为什么要用 const K 呢?上节课说了, set 里面的 K 不能改变!一旦改变就会破坏 好不容易排好的顺序,以后再用二分法 find 就找不准了,所以 set 实际上只有 const_iterator 。 • 但是 map 只针对 K 进行排序, V 又不参与排序,完全可以随意改变。因此 C++ 之父 允许 map 从小到大的顺序。 k k k k k k v v v v v v 小 大 第三章:二叉排序树 高效的查找离不开我 高效的查找离不开我 回顾 set 容器 • 上一期 (BV1m34y157wb) ,我们已经讲了 set 容器,特点是自动去重 + 高效查找。 • set 容器中的类型通过模板来指定: set • set 容器又可以分为 set 、 multiset 、 0 码力 | 90 页 | 8.76 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程
继续锐评黄某勋 • 感兴趣的扣 1 • OpenMP 新特性( parallel for 之外的) • SIMD 指令全解析( mm 开头那堆) • 内存与缓存优化进阶(第七课的延伸) • 二分查找法优化案例(针对缓存行的) • eigen 、 glm 、 vectorclass 等常用库(可能) • CPU 红黑高斯 + 多重网格实战 • 继续锐评因特尔 • 感兴趣的扣 20 码力 | 142 页 | 13.52 MB | 1 年前3Rust 异步并发框架在移动端的应用 - 陈明煜
Fusion of IO/CPU intensive IO & CPU 融合 Fusion of IO/CPU intensive 南向调度融合:异步并行迭代器 将数据容器内的数据进行递归二分,对左 半和右半分别生成一个异步任务。最终对 单个数据执行用户业务逻辑 IO & CPU 融合 南向调度融合 IO & CPU 通过设置不同优先级,进 入不同线程池调度 线程池根据负载监控(任务平均等待0 码力 | 25 页 | 1.64 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 16 现代 CMake 模块化项目管理指南
六、头文件和源文件的一一对应关系 • 通常每个头文件都有一个对应的源文件,两个文件名字应当相同 (方便我们理解,也方便 IDE 跳转),只有后缀名不一样。 • 如果是一个类,则文件名应和类名相同,方便查找 ( Animal.cpp )。 • 头文件中包含函数和类的声明,源文件则包含他们的实现。 七、只有头文件,没有源文件的情况 • 有时我们会直接把实现直接写在头文件里,这时可以没有与之对 应的源文件,只有一个头文件。 中的所有路径下查找 XXX.cmake 这个文件。 • 这样你可以在 XXX.cmake 里写一些你常用的函数,宏,变量等。 十三、你知道吗? CMake 也有 include 功能 • 和 C/C++ 的 #include 一样, CMake 也有一个 include 命令。 • 你写 include(XXX) ,则他会在 CMAKE_MODULE_PATH 这个列表 中的所有路径下查找 XXX find_package(OpenCV) • 查找名为 OpenCV 的包,找不到不报错,事后可以通过 ${OpenCV_FOUND} 查询是否找到。 • find_package(OpenCV QUIET) • 查找名为 OpenCV 的包,找不到不报错,也不打印任何信息。 • find_package(OpenCV REQUIRED) # 最常见用法 • 查找名为 OpenCV 的包,找不到就报错(并终止0 码力 | 56 页 | 6.87 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 15 C++ 系列课:字符与字符串
• 为什么最后两个重载没有标记 noexcept ?历史原因,实际上 find 函数都是不会抛出异常的,他找不到只会返回 -1 。 find 寻找子字符串 • find(‘c’) 会在字符串中查找字符 ‘ c’ ,如果找到,返回这个字符第 一次出现所在的位置。如果找不到,返回 -1 。 • 注意:如果原字符串中 ‘ c’ 出现了多次,则只会返回第一个出现的 位置。例如 “ icatchthecat” ,而计算机数数从 0 开始,所以他认为是第 1 个没 毛病。 • find(‘c’, pos) 会在字符串中查找字符 ‘ c’ ,不同的是他会从第 pos 个字符开始,例如 “ icatchthecat”.find(‘c’, 3) 会返回 4 ,因为是从 第 3 个字符 ‘ t’ 开始查找(人类看来是第四个),所以第一个 ‘ c’ 被略过。 • 如果 pos 所在的位置刚好就是 ‘ c’ ,那么会返回 ,那么会返回 pos ,例如 “ icatchthecat”.find(‘c’, 4) 会返回 4 。 find 寻找子字符串 • find(‘c’) 会在字符串中查找字符 ‘ c’ ,如果找到,返回这个字符第 一次出现所在的位置。如果找不到,返回 -1 。 • 注意:如果原字符串中 ‘ c’ 出现了多次,则只会返回第一个出现的 位置。例如 “ icatchthecat”.find(‘c’)0 码力 | 162 页 | 40.20 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 11 现代 CMake 进阶指南
另一种方式:先创建目标,稍后再添加源文件 如果有多个源文件呢? 逐个添加即可 使用变量来存储 建议把头文件也加上,这样在 VS 里可以出现在“ Header Files” 一栏 使用 GLOB 自动查找当前目录下指定扩展名的文件,实现批量添加源文件 启用 CONFIGURE_DEPENDS 选项,当添加新文件时,自动更新变量 如果源码放在子文件夹里怎么办? 必须把路径名和后缀名的排列组合全部写出来吗?感觉好麻烦 对动态链接很不友好) 常见问题:老师,我链接了自己的 dll ,但是为什么运行时会找不到? • 这是因为你的 dll 和 exe 不在同一目录。 Windows 比较蠢,他只会找当前 exe 所在目 录,然后查找 PATH ,找不到就报错。而你的 dll 在其他目录,因此 Windows 会找不到 dll 。 • 解决 1 :把 dll 所在位置加到你的 PATH 环境变量里去,一劳永逸。 • 解决 2 patchelf 命令。 yyds 第 5 章:链接第三方库 案例:需要使用 tbb 这个库 直接链接 tbb 的缺点 如果这样直接指定 tbb , CMake 会让链接器在系统的库目录里查找 tbb , 他会找到 /usr/lib/libtbb.so 这个系统自带的,但这对于没有一个固定库安装位 置的 Windows 系统并不适用。 此外,他还要求 tbb 的头文件就在 /usr/include0 码力 | 166 页 | 6.54 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 07 深入浅出访存优化
的厂商早就意识到了内存延迟高,读写效率低 下的问题。因此他们在 CPU 内部引入了一片极小的存储 器——虽然小,但是读写速度却特别快。这片小而快的 存储器称为缓存( cache )。 • 当 CPU 访问某个地址时,会先查找缓存中是否有对应的 数据。如果没有,则从内存中读取,并存储到缓存中; 如果有,则直接使用缓存中的数据。 • 这样一来,访问的数据量比较小时,就可以自动预先加 载到这个更高效的缓存里,然后再开始做运算,从而避 • uint64_t address; • char data[64]; • }; • CacheEntry cache[512]; • 当 CPU 读取一个地址时: • 缓存会查找和该地址匹配的条目。如果找到,则给 CPU 返 回缓存中的数据。如果找不到,则向主内存发送请求,等读 取到该地址的数据,就创建一个新条目。 • 在 x86 架构中每个条目的存储 64 字节的数据,这个条目 • uint64_t address; • char data[64]; • }; • CacheEntry cache[512]; • 当 CPU 写入一个地址时: • 缓存会查找和该地址匹配的条目。如果找到,则修改缓存 中该地址的数据。如果找不到,则创建一个新条目来存储 CPU 写的数据,并标记为脏( dirty )。 • 当读和写创建的新条目过多,缓存快要塞不下时,他会把0 码力 | 147 页 | 18.88 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 01 学 C++ 从 CMake 学起
跳转到动态加载的地址去。 • Windows :可执行文件同目录,其次是环境变量 %PATH% • Linux : ELF 格式可执行文件的 RPATH ,其次是 /usr/lib 等 运行时查找 编译时插入 CMake 中的静态库与动态库 • CMake 除了 add_executable 可以生成可执行文件外,还可以通过 add_library 生成库 文件。 • add_library OpenMP::OpenMP_CXX • 不同的包之间常常有着依赖关系,而包管理器的作者为 find_package 编写的脚本(例如 /usr/lib/cmake/TBB/TBBConfig.cmake )能够自动查找所有依赖,并利用刚刚提 到的 PUBLIC PRIVATE 正确处理依赖项,比如如果你引用了 OpenVDB::openvdb 那么 TBB::tbb 也会被自动引用。 • 其他包的引用格式和文档参考:0 码力 | 32 页 | 11.40 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 性能优化之无分支编程 Branchless Programming
对于自变量不连续的情况:查表法需要从数组变成 map • 不过把 lut 作为数组的方法只适用于自变量 x 连 续变化的情况,如果不连续,则只好采用 map 查表了(相当于 Python 的字典)。 • 不过 map 的查找开销更大,复杂度为 O(logn) ,比线性数组的 O(1) 要坏一点点。 • 所以采用 map 也可能导致反而比暴力 if-else 更 低效,也可能高效,要测试才知道。 • 抛开性能不谈,从可读性和可维护性上来 • 注:实际中虚函数往往有很多个,为了存储空间的高效利用,会把多个虚函数打包成一个数组,称之 为“虚函数表( vtable )”。这样一来,类成员里只需要存一个指向虚函数表首地址的指针,之后通过 查找该表即可找到连续的 n 个函数指针。此处为了方便理解,右侧案例代码没有用虚函数表。 课外拓展 · 参考资料 • 堆栈和 ABI 的知识 https://zhuanlan.zhihu.com/p/273391910 码力 | 47 页 | 8.45 MB | 1 年前3
共 14 条
- 1
- 2