C++高性能并行编程与优化 - 课件 - 11 现代 CMake 进阶指南
构建工程的产生器。它将产生构建文件 (e.g. "Unix Makefiles", "Visual Studio 2019", etc.) 一个标准的 CMakeLists.txt 模板 第 3 章:链接库文件 main.cpp 调用 mylib.cpp 里的 say_hello 函数 改进: mylib 作为一个静态库 改进: mylib 作为一个动态库 改进: mylib 作为一个对象库 静态库的麻烦: GCC 编译器自作聪明,会自动剔除没有引用符号的那些对 象 对象库可以绕开编译器的不统一:保证不会自动剔除没引用到的对象文件 虽然动态库也可以避免剔除没引用的对象文件,但引入了运行时链接的麻烦 add_library 无参数时,是静态库还是动态库 ? 会根据 BUILD_SHARED_LIBS 这个变量的值决定是动态库还是静态库。 ON 则相当于 SHARED , OFF 则相当于 BUILD_SHARED_LIBS 这个变量时,会默认变成 ON 。 也就是说除非用户指定了 -DBUILD_SHARED_LIBS:BOOL=OFF 才会生成 静态库,否则默认是生成动态库。 常见坑点:动态库无法链接静态库 解决:让静态库编译时也生成位置无关的代码 (PIC) ,这样才能装在动态库 里 也可以只针对一个库,只对他启用位置无关的代码 (PIC) 第 4 章:对象的属性 除了 POSITION_INDEPENDENT_CODE0 码力 | 166 页 | 6.54 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 16 现代 CMake 模块化项目管理指南
则仅考虑该子项目自身的设定,比 如他的头文件目录,要链接的库等等。 四、子项目的头文件 • 这里我们给 biology 设置了头文件搜索路径 include 。 • 因为子项目的 CMakeLists.txt 里指定的路径都是相对路径 ,所以这里指定 include 实际上是:根 /biology/include 。 • 注意我们用了 PUBLIC 修饰符,这是为了让链接 biology 的 pybmain 格”的第三方库也暴露个全局的 Animal ,两个符号就会发生冲突,由于类符号 都具有 weak 属性,链接器会随机选择一个覆盖掉,非常危险! • (关于符号的 weak 属性,以后单独开一门 C++ 课讲讲,这一课还是重点关注 CMake ) 十二、依赖另一个子项目,则需要链接他 • 让 pybmain 链接上 biology : target_link_libraries(pybmain PUBLIC 中则是基于定义者所在路径,优先访问定义者的作用域。这里需要 set(key val PARENT_SCOPE) 才能修改到外面的变量。 第二章:第三方库 / 依赖项配置 用 find_package 寻找系统中安装的第三方库并链接他们 find_package 命令 • 常用参数列表一览: • find_package([version] [EXACT] [QUIET] [CONFIG] [MODULE] 0 码力 | 56 页 | 6.87 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 01 学 C++ 从 CMake 学起
函数,并在终端显示出 Hello, world 。 厂商 C C++ Fortran GNU gcc g++ gfortran LLVM clang clang++ flang 多文件编译与链接 • 单文件编译虽然方便,但也有如下缺点: 1. 所有的代码都堆在一起,不利于模块化和理解。 2. 工程变大时,编译时间变得很长,改动一个地方就得全部重新编译。 • 因此,我们提出多文件编译的概念,文件之间通过符号声明相互引用。 main.o • 其中使用 -c 选项指定生成临时的对象文件 main.o ,之后再根据一系列对象文件进行链接 ,得到最终的 a.out : • > g++ hello.o main.o -o a.out 为什么需要构建系统( Makefile ) • 文件越来越多时,一个个调用 g++ 编译链接会变得很麻烦。 • 于是,发明了 make 这个程序,你只需写出不同文件之间的依赖关系,和生成各文件的规则。 会讨论如何使用他人的库。 • 创建库以后,要在某个可执行文件中使用该库,只需要: • target_link_libraries(myexec PUBLIC test) # 为 myexec 链接刚刚制作的库 libtest.a • 其中 PUBLIC 的含义稍后会说明( CMake 中有很多这样的大写修饰符) 为什么 C++ 需要声明 • 在多文件编译章中,说到了需要在 main.cpp0 码力 | 32 页 | 11.40 MB | 1 年前3C++高性能并行编程与优化 - 课件 - Zeno 中的现代 C++ 最佳实践
三方库里写死的,这个第三方库的作者可能没 上过《面向对象程序设计》,居然没有定义一 个公用的 Animal 基类并设一个 speak 为虚 函数。现在你抱怨也没有用,因为这个库是按 LGPL 协议开源的,你只能链接他,不能修改 他的源码,但你的老板却要求你把 speak 变 成一个虚函数!怎么样,是不是准备好递交辞 呈了?慢着,让万能的小彭老师来救你! 类型擦除:还是以猫和狗为例 • 你还是可以照常定义一个 声明为 extern std::map<...> functab; • 慢着,这样会有一定的几率出现 segfault ! • 就是说,如果 functab 所在的 main.o 文 件在链接中是处于 cat.o 和 dog.o 后面 的话,那么 cat.o 和 dog.o 的静态初始 化就会先被调用,这时候 functab 的 map 还没有初始化( map 的构造函数也 是静态初始化!)从而会调用未初始化的 before_main )里 使用了函数静态初始化( Helper )会怎样? • 会让函数静态初始化( Helper )执行得比全 局静态初始化( before_main )还早! 用包装,避免因为链接的不确定性打乱了静态初始化的顺序 • 利用这个发现,我们意识到可以把 functab 用所谓的“懒汉单例模式”包装成一 个 getFunctab() 函数,里面的 inst 变量 会在第一次进入的时候初始化。因为第一0 码力 | 54 页 | 3.94 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 04 从汇编角度看编译器优化
发现:会让编译变得很慢,因为这 50000 次迭代是在编译期进行的。 第 2 章:内联 调用外部函数: call 指令 @PLT 是 Procedure Linkage Table 的缩 写,即函数链接表。链接器会查找其他 .o 文件中是否定义了 _Z5otheri 这个符号, 如果定义了则把这个 @PLT 替换为他的地 址。 对 PLT 感兴趣?看 https://www.cnblogs.com t-plt.html 编译器优化: call 变 jmp 多个函数定义在同一个文件中 如果 _Z5otheri 定义在同一个文件中,编 译器会直接调用,没有 @PLT 表示未定义 对象。减轻了链接器的负担。 编译器优化:内联化 只有定义在同一个文件的函数可以被内联 !否则编译器看不见函数体里的内容怎么 内联呢? 为了效率我们可以尽量把常用函数定义在 头文件里,然后声明为 static 。这样调用0 码力 | 108 页 | 9.47 MB | 1 年前3应用 waPC (rust) 做软件测试工具
模拟数据 • 发 RPC 请求 • 可以上传 proto 文档 • 可以验证数据 前段链接 Wasm Mock Server 随机 waPC 注册逻辑 Use wasm without fear 支持以 websocket 代替 wasm 协议 • 不可能为每个 websocket 链接编程新的 wasm • 流氓做法 (fork) - waPC guest rust 可 改编成让0 码力 | 30 页 | 2.50 MB | 1 年前3Zadig 产品使用手册
工程化协同:“人、技术、流 程、工具” 四维协同基线,沉 淀全流程数据,从感知到赋 能,服务于工程师 释放云基建能力:链接任何云 及自建资源(容器、主机、车 机、端等),释放云原生价值 和企业创新力 生态开放:广泛开放系统 模块和 OpenAPI ,链接 一切流程、服务、工具和 上下游伙伴 安全简单自主可控:私有化 部署,现有服务 0 迁移成本 、体验丝滑接入容易、学习0 码力 | 52 页 | 22.95 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 05 C++11 开始的多线程编程
这样就可以一边和用户交互,一边在另一 个线程里慢吞吞下载文件了。 错误:找不到符号 pthread_create • 但当我们直接尝试编译刚才的代码,却在链接时发生了错误。 • 原来 std::thread 的实现背后是基于 pthread 的。 • 解决: CMakeLists.txt 里链接 Threads::Threads 即可: 有了多线程:异步处理请求 • 有了多线程的话,文件下载和用户交互分 别在两个线程,同时独立运行。从而下载0 码力 | 79 页 | 14.11 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程
编译器具有多段编译的特点。 • 一段代码他会先送到 CPU 上的编译器(通常是系统自带的编译 器比如 gcc 和 msvc )生成 CPU 部分的指令码。然后送到真 正的 GPU 编译器生成 GPU 指令码。最后再链接成同一个文件 ,看起来好像只编译了一次一样,实际上你的代码会被预处理很 多次。 • 他在 GPU 编译模式下会定义 __CUDA_ARCH__ 这个宏,利用 #ifdef 判断该宏是否定义,就可以判断当前是否处于 various-nvidia-cards/ 更老的版本如 GT-630 已经被 CUDA 11 废除,因此本课程要 求同学有 GTX900 及以上显卡。如果需要在老显卡上运行的话 ,可以看下面那个链接,查一下你的显卡对应的版本号是多少 ,然后在 CMake 里设置个一样的,应该就能用了。 小彭老师每日锐评 • 顺便, Pascal 、 Turing 、 Ampere 什么的高大上架构名,那个是老黄拿来营销用的。0 码力 | 142 页 | 13.52 MB | 1 年前3Rust与算法 - 谢波
总体来看,时间复杂度没有超过 O(n) 的! Rust 实现数据结构 • 栈 • 链表 • Vec Rust 实现数据结 构 栈 借助 Vec 容器 泛型支持 Option ? 链表 链接可能为空 多种迭代 Vec 借助链表 随机插入 插入新的 Vec Rust 实现算法 • 蒂姆排序 • 字典树 • 图 Rust 实现算 法 蒂姆排序 什么是蒂姆排序? 蒂姆排序0 码力 | 28 页 | 3.52 MB | 1 年前3
共 14 条
- 1
- 2