基于Rust-vmm实现Kubernetes运行时0 码力 | 27 页 | 34.17 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 03 现代 C++ 进阶:模板元编程传入的 N ,是一个编译期常量,每个不同的 N ,编译器都会单独生成一份代码,从而可以对他做单独的优化 。 • 而 func(int N) ,则变成运行期常量,编译器无法自动优化,只 能运行时根据被调用参数 N 的不同。 • 比如 show_times<0>() 编译器就可以自动优化为一个空函数。 因此模板元编程对高性能编程很重要。 • 通常来说,模板的内部实现需要被暴露出来,除非使用特殊的手 • 在右边这个案例中,我们声明了一个 sumto 函数,作用是求出从 1 到 n 所有 数字的和。 • 用一个 debug 参数控制是否输出调试信 息。 • 但是这样 debug 是运行时判断,这样即 使是 debug 为 false 也会浪费 CPU 时 间。 模板的应用:编译期优化案例(续) • 因此可以把 debug 改成模板参数,这样 就是编译期常量。编译器会生成两份函数 (下一讲会深入分析编译器的工作原理) 模板的难题:编译期常量的限制 • 编译期常量的限制就在于他不能通过运行时变量组成的表达式来指定。比如: • 这里在 if constexpr 的表达式里用到了运行时变量,从而无法作为编译期分支的条件。 模板的难题:编译期常量的限制(续) • 除了 if constexpr 的表达式不能用运行时变量,模板尖括号内的参数也不能: • 可以在 bool debug 变量的定义前面加上0 码力 | 82 页 | 12.15 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 15 C++ 系列课:字符与字符串• 而 \ 比较厉害,他是编译器内部专门为他“开了个后门”。 • 编译器检测到字符串中出现 \ 就会把下一个字符特殊处理。 • 而 % ,编译器并不会特殊处理 % ,是 printf 函数内部在运行时处理了 % 的下一个字符。 • % 就像你和同学随手“拉钩”定下的约定,这是 printf 约定俗成的。 • \ 就像正式合同,有法律效力的,这是 C 语言编译器规定好的。 C++ 字符串类 的返回值已经是 int 了,要额外的返回值只能这样 。 stoi 的第二参数: &pos stoi 的 &pos 参数实战案例 stoi 抛出异常的情况 • 如果字符串的开头不是数字,则 stoi 会抛出 std::invalid_argument 异常,可以用 catch 捕 获。 • 但是开头可以有空格,例如 stoi(“ 42yuan”) 可以正常得到 42 ,但 stoi(“my42yuan”) 越界的情况,也就是检测到 i ≥ s.size() 时,会抛出 std::out_of_range 异常终止程序。使用 gdb 等调试 器就可以在出这个异常的时候暂停,帮你调试错误 ( BV1kP4y1K7Eo )。也可以从外部函数 catch 住这个异常(以 后再讲)。 • 而 [] 则不会抛出异常,他只是简单地给字符串的首地址指针和 i 做个加法运算,得到新的指针并解引用。如果你给的 i 超过了字符0 码力 | 162 页 | 40.20 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程系列显卡的。 • 不过英伟达的架构版本都是向前兼容的,即版本号为 75 的 RTX2080 也可以运行版本号为 52 的指令码,虽然 不够优化,但是至少能用。也就是要求:编译期指定的 版本 ≤ 运行时显卡的版本。 CMAKE_CUDA_ARCHITECTURES 会自动转换成 --gpu-code 等编 译 flag 版本号不要太新了 • 比如这里设置了 RTX3000 系列的架构版 本号 一样!所以一定 要注意调对你的版本号。否则就会这样 kernel 好像没有执行过一样,只有 CPU 上的代码被执行了。 指定多个版本号 • 可以指定多个版本号,之间用分号分割。 • 运行时可以自动选择最适合当前显卡的版 本号,通常用于打包发布的时候。 • 不过这样会导致 GPU 编译器重复编译很 多遍,每次针对不同的架构,所以编译会 变得非常慢,生成的可执行文件也会变大 。 ret 的值并没有被改写成 功。 分析返回的错误代码 • CUDA 的函数,如 cudaDeviceSynchronize() 。 • 他们出错时,并不会直接终止程序,也不会抛出 C++ 的异常,而是返回一个错误代码,告诉你出的具体什么 错误,这是出于通用性考虑。 • 这个错误代码的类型是 cudaError_t ,其实就是个 enum 类型,相当于 int 。 • 可以通过 cudaGetErrorName0 码力 | 142 页 | 13.52 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 17 由浅入深学习 map 容器通过实战案例来学习 STL 算法库 7. C++ 标准输入输出流 & 字符串格式化 8. traits 技术,用户自定义迭代器与算法 9. allocator ,内存管理与对象生命周期 10. C++ 异常处理机制的前世今生 我们都要认真鞋习哦 我们都要认真鞋习哦 第一章:读取与写入 我负责监督你鞋习 ! 我负责监督你鞋习 ! map 查找元素的两个接口 • map 提供了两个查找元素的接口,一曰 key” 元素 • val = m.at(“key”); // 读取键值为 “ key” 的元素,如果不存在,抛出异常 • 所以 [] 和 at() 唯一的区别,在于键值不存在这一特殊情况的处理方式。 • [] 默默创建。 • at() 抛出异常。 读取 map 元素 • mapm; • val = m[“key”]; • 读取键值为 “ key” it->second; 读取 map 元素 • map m; • val = m.at(“key”); • 读取键值为 “ key” 的元素,如果不存在,那就抛出异常,导致程序异常退出。等价于: • it = m.find(“key”); • if (it == m.end()) { • throw std::out_of_range(“ 找不到键值” ); 0 码力 | 90 页 | 8.76 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 11 现代 CMake 进阶指南: 该平台上可执行程序的后缀。 • CMAKE_SIZEOF_VOID_P: void 指针的大小。 • CMAKE_SKIP_RPATH: 如果为真,将不添加运行时路径信息。默认情况下是如果平台支持运行时信息 ,将会添加运行时信息到可执行程序当中。这样从构建树中运行程序将很容易。为了在安装过程中忽略 掉 RPATH ,使用 CMAKE_SKIP_INSTALL_RPATH 。 • CMAKE_GENERATOR: 静态库的麻烦: GCC 编译器自作聪明,会自动剔除没有引用符号的那些对 象 对象库可以绕开编译器的不统一:保证不会自动剔除没引用到的对象文件 虽然动态库也可以避免剔除没引用的对象文件,但引入了运行时链接的麻烦 add_library 无参数时,是静态库还是动态库 ? 会根据 BUILD_SHARED_LIBS 这个变量的值决定是动态库还是静态库。 ON 则相当于 SHARED , OFF 则相当于 译器。 假如你一定要用动态链接库( Windows 对动态链接很不友好) 假如你一定要用动态链接库( Windows 对动态链接很不友好) 常见问题:老师,我链接了自己的 dll ,但是为什么运行时会找不到? • 这是因为你的 dll 和 exe 不在同一目录。 Windows 比较蠢,他只会找当前 exe 所在目 录,然后查找 PATH ,找不到就报错。而你的 dll 在其他目录,因此 Windows0 码力 | 166 页 | 6.54 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 02 现代 C++ 入门:RAII 内存管理解构函数是显式的,离开作用域自动销毁,毫不含 糊(有好处也有坏处,对高性能计算而言利大于 弊) 如果没有解构函数,则每个带有返回的分 支都要手动释放所有之前的资源 : RAII :异常安全( exception-safe ) C++ 标准保证当异常发生时,会调用已创建对象的解构函数 。 因此 C++ 中没有(也不需要) finally 语句。 如果此处不关闭,则可等 待稍后垃圾回收时关闭。 虽然最后还是关了,但如 如果需要允许用户拷贝你的 Vector 类对象 ,我们还是需要实现一下的。 • 发现了吗?其实不管是 size/resize 这样的 get/set 模式也好;自定义的拷贝构造函数 也好; RAII 保证异常安全也好;都是在为 面向对象思想的“封装:不变性”服务。 • 即:保证任何单个操作前后,对象都是处于 正确的状态,从而避免程序读到错误数据 (如空悬指针)的情况。 三五法则:拷贝赋值函数0 码力 | 96 页 | 16.28 MB | 1 年前3
Rust 异步并发框架在移动端的应用 - 陈明煜的场景。具有非常强大的生 态。 tokio 第一个适配 Rust async/await 原语 的运行时库,与 tokio 类似支持异步 IO ,目前已经半废弃 async-std 更轻量化的调度框架,功能被拆分 到其他多个库中, IO 密集场景性 能不如 Tokio smol Rayon 并非异步运行时。它通过同步 多线程模型提供了并行迭代器功能, 适用于处理 CPU 密集型计算任务 rayon0 码力 | 25 页 | 1.64 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 13 C++ STL 容器全解之 vectoroperator[] • 值得注意的是, [] 运算符在索引超出数组大 小时并不会直接报错,这是为了性能的考虑。 • 如果你不小心用 [] 访问了越界的索引,可能 会覆盖掉别的变量导致程序行为异常,或是访 问到操作系统未映射的区域导致奔溃。 • int &operator[](size_t i) noexcept; • int const &operator[](size_t i) const noexcept; vector 容器: at • 为了防止不小心越界,可以用 a.at(i) 替代 a[i] , at 函数会检测索引 i 是否越界,如果他 发现索引 i >= a.size() 则会抛出异常 std::out_of_range 让程序提前终止(或者被 try-catch 捕获),配合任意一款调试器,就可 以很快速地定位到出错点。 • 不过 at 需要额外检测下标是否越界,虽然更安0 码力 | 90 页 | 4.93 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 04 从汇编角度看编译器优化的,一份是传统标量的 他在运行时检测 a, b 指针的差是否超过 1024 来判断是否有重叠现 象。 1. 如果没有重叠,则跳转到 SIMD 版本高效运行。 2. 如果重叠,则跳转到标量版本低效运行,但至少不会错。 SIMD 版 标量版 循环中的矢量化:解决指针别名 所以,让我们加上 __restrict 关键字,打消编译器的顾虑! 这下只需要生成一个 SIMD 版本了,没有了运行时判断重叠的焦虑。0 码力 | 108 页 | 9.47 MB | 1 年前3
共 17 条
- 1
- 2













