C++高性能并行编程与优化 - 课件 - 11 现代 CMake 进阶指南// 调用本地的构建系统执行 install 这个目标,即安 装 -D 选项:指定配置变量(又称缓存变量) • 可见 CMake 项目的构建分为两步: • 第一步是 cmake -B build ,称为配置阶段( configure ),这时只检测环境并生成构建规则 • 会在 build 目录下生成本地构建系统能识别的项目文件( Makefile Makefile 或是 .sln ) • 第二步是 cmake --build build ,称为构建阶段( build ),这时才实际调用编译器来编译代码 • 在配置阶段可以通过 -D 设置缓存变量。第二次配置时,之前的 -D 添加仍然会被保留。 • cmake -B build -DCMAKE_INSTALL_PREFIX=/opt/openvdb-8.0 • ↑ 设置安装路径为 /opt/openvdb-8 • cmake -B build -DCMAKE_BUILD_TYPE=Release • ↑ 设置构建模式为发布模式(开启全部优化) • cmake -B build ← 第二次配置时没有 -D 参数,但是之前的 -D 设置的变量都会被保留 • (此时缓存里仍有你之前定义的 CMAKE_BUILD_TYPE 和 CMAKE_INSTALL_PREFIX ) -G 选项:指定要用的生成器0 码力 | 166 页 | 6.54 MB | 1 年前3
《深入浅出MFC》2/eMFC 程序设计》(编按:深入浅出MFC 简体版),对我有非常大的帮助。在 此,先感谢您。现在我感到对C++ 语言本身和MFC 框架十分了解,但在编程过程中仍然 感到生疏,主要是函数的运用和函数的参数十分复杂。我对WINDOWS SDK 编程较少,是 否应该要熟悉WINDOWS API 函数后,结合MFC 框架编程? 侯俊杰回复:的确如此。MFC 其实就是把Windows API 做了一层薄薄包装,包装于各个设 MFC 預設的印表機制 / 669 Scribble 列印機制的補強 / 685 印表機的頁和文件的頁 / 685 配置 GDI 繪圖工具 / 687 尺寸與方向:關於映像模式(座標系統) / 688 分頁 / 693 表頭(Header)與表尾(Footer)/ RC #0059 wc.lpszClassName = _szAppName; #0060 程序名称 窗口标题 程序进入点 避免编译时的警告 传回 PostQuitMessage 的参数 注册窗口类别 窗口函数 窗口背景颜色 所定义的菜单 12 #0061 return (RegisterClass(&wc)); #0062 } #0063 //--------0 码力 | 1009 页 | 11.08 MB | 1 年前3
Hello 算法 1.1.0 C++ 版是找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况。这种评估方式能够反映真 实情况,但也存在较大的局限性。 一方面,难以排除测试环境的干扰因素。硬件配置会影响算法的性能。比如在某台计算机中,算法 A 的运行 时间比算法 B 短;但在另一台配置不同的计算机中,可能得到相反的测试结果。这意味着我们需要在各种机 器上进行测试,统计平均效率,而这是不现实的。 另一方面,展开完整测试非常耗费资源。 1. 递:程序不断深入地调用自身,通常传入更小或更简化的参数,直到达到“终止条件”。 2. 归:触发“终止条件”后,程序从最深层的递归函数开始逐层返回,汇聚每一层的结果。 而从实现的角度看,递归代码主要包含三个要素。 1. 终止条件:用于决定什么时候由“递”转“归”。 2. 递归调用:对应“递”,函数调用自身,通常输入更小或更简化的参数。 3. 返回结果:对应“归”,将当前递归层级的结果返回至上一层。 尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无须继续执行其他 操作,因此系统无须保存上一层函数的上下文。 以计算 1 + 2 + ⋯ + ? 为例,我们可以将结果变量 res 设为函数参数,从而实现尾递归: // === File: recursion.cpp === /* 尾递归 */ int tailRecur(int n, int res) { // 终止条件 if (n0 码力 | 379 页 | 18.47 MB | 1 年前3
Hello 算法 1.0.0 C++版是找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况。这种评估方式能够反映真 实情况,但也存在较大的局限性。 一方面,难以排除测试环境的干扰因素。硬件配置会影响算法的性能。比如在某台计算机中,算法 A 的运行 时间比算法 B 短;但在另一台配置不同的计算机中,可能得到相反的测试结果。这意味着我们需要在各种机 器上进行测试,统计平均效率,而这是不现实的。 另一方面,展开完整测试非常耗费资源。 1. 递:程序不断深入地调用自身,通常传入更小或更简化的参数,直到达到“终止条件”。 2. 归:触发“终止条件”后,程序从最深层的递归函数开始逐层返回,汇聚每一层的结果。 而从实现的角度看,递归代码主要包含三个要素。 1. 终止条件:用于决定什么时候由“递”转“归”。 2. 递归调用:对应“递”,函数调用自身,通常输入更小或更简化的参数。 3. 返回结果:对应“归”,将当前递归层级的结果返回至上一层。 尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无须继续执行其他 操作,因此系统无须保存上一层函数的上下文。 以计算 1 + 2 + ⋯ + ? 为例,我们可以将结果变量 res 设为函数参数,从而实现尾递归: // === File: recursion.cpp === /* 尾递归 */ int tailRecur(int n, int res) { // 终止条件 if (n0 码力 | 378 页 | 17.59 MB | 1 年前3
Hello 算法 1.0.0b5 C++版是找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况。这种评估方式能够反映真 实情况,但也存在较大局限性。 一方面,难以排除测试环境的干扰因素。硬件配置会影响算法的性能表现。比如在某台计算机中,算法 A 的 运行时间比算法 B 短;但在另一台配置不同的计算机中,我们可能得到相反的测试结果。这意味着我们需要 在各种机器上进行测试,统计平均效率,而这是不现实的。 另一方面,展开完整测试非常耗费 1. 递:程序不断深入地调用自身,通常传入更小或更简化的参数,直到达到“终止条件”。 2. 归:触发“终止条件”后,程序从最深层的递归函数开始逐层返回,汇聚每一层的结果。 而从实现的角度看,递归代码主要包含三个要素。 1. 终止条件:用于决定什么时候由“递”转“归”。 2. 递归调用:对应“递”,函数调用自身,通常输入更小或更简化的参数。 3. 返回结果:对应“归”,将当前递归层级的结果返回至上一层。 尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无需继续执行其他 操作,因此系统无需保存上一层函数的上下文。 以计算 1 + 2 + ⋯ + ? 为例,我们可以将结果变量 res 设为函数参数,从而实现尾递归。 // === File: recursion.cpp === /* 尾递归 */ int tailRecur(int n, int res) { // 终止条件 if (n0 码力 | 377 页 | 30.69 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 16 现代 CMake 模块化项目管理指南左图的案例中,我们在根目录下,创建了 两个子项目 biology 和 pybmain ,他们 分别在各自的目录下有自己的 CMakeLists.txt 。 二、根项目的 CMakeLists.txt 配置 • 在根项目的 CMakeLists.txt 中,设置了默 认的构建模式,设置了统一的 C++ 版本 等各种选项。然后通过 project 命令初始 化了根项目。 • 随后通过 add_subdirectory biology 添加进来(顺序 无关紧要),这会调用 pybmain/CMakeLists.txt 和 biology/CMakeLists.txt 。 三、子项目的 CMakeLists.txt 配置 • 子项目的 CMakeLists.txt 就干净许多,只是创建了 biology 这个静态库对象,并通过 GLOB_RECRUSE 为他批量添加 了所有位于 src 和 include 下源码和头文件。 中则是基于定义者所在路径,优先访问定义者的作用域。这里需要 set(key val PARENT_SCOPE) 才能修改到外面的变量。 第二章:第三方库 / 依赖项配置 用 find_package 寻找系统中安装的第三方库并链接他们 find_package 命令 • 常用参数列表一览: • find_package([version] [EXACT] [QUIET] [CONFIG] 0 码力 | 56 页 | 6.87 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 15 C++ 系列课:字符与字符串必须告诉他是字符串( %s )还是整数( %d )还是 字符( %c ),必须和右边的参数一致,初学者容易搞错 。 • 而且即使搞错了也能正常编译通过(一些高级的编译器会 给出警告),但是运行结果不对,或者还有可能崩溃。 泛型的 iostream 应运而生 • 得益于 C++ 的重载技术, cout 不用你手动指定类型,他 会自动识别参数的类型,帮你调用相应的格式化函数。 c_str 和 data 的区别 data() 只保证返回长度为 s.size() 的连续内存的首地址指针,不保证 0 结 尾。 • 把 C++ 的 string 作为参数传入像 printf 这种 C 语言函数时,需要用 s.c_str() 。 • 如果只是在 C++ 函数之间传参数,直接用 string 或 string const & 即可。 • void legacy_c(const char *name); stoi(“42”) 等价,都会返回 42 。后面的 “ yuan” 会被 stoi 略去。 • 那如何才能知道哪些字符被 stoi 略去了呢?或者说,数字部分从哪里结束? • 这就要用到 stoi 的第二参数,他是一个 size_t 的指针,默认为 nullptr 。 • 若该指针不为 nullptr ,则会往他指向的变量写入一个整数,表示数字部分结 束的那个字符所在的位置,很绕口?来看个例子就懂了。0 码力 | 162 页 | 40.20 MB | 1 年前3
Hello 算法 1.2.0 简体中文 C++ 版法的效率。最直接的方法 是找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况。这种评估方式能够反映真 实情况,但也存在较大的局限性。 一方面,难以排除测试环境的干扰因素。硬件配置会影响算法的性能表现。比如一个算法的并行度较高,那 么它就更适合在多核 CPU 上运行,一个算法的内存操作密集,那么它在高性能内存上的表现就会更好。也 就是说,算法在不同的机器上的测试结果可能是 1. 递:程序不断深入地调用自身,通常传入更小或更简化的参数,直到达到“终止条件”。 2. 归:触发“终止条件”后,程序从最深层的递归函数开始逐层返回,汇聚每一层的结果。 而从实现的角度看,递归代码主要包含三个要素。 1. 终止条件:用于决定什么时候由“递”转“归”。 2. 递归调用:对应“递”,函数调用自身,通常输入更小或更简化的参数。 3. 返回结果:对应“归”,将当前递归层级的结果返回至上一层。 尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无须继续执行其他 操作,因此系统无须保存上一层函数的上下文。 以计算 1 + 2 + ⋯ + ? 为例,我们可以将结果变量 res 设为函数参数,从而实现尾递归: // === File: recursion.cpp === /* 尾递归 */ int tailRecur(int n, int res) { // 终止条件 if (n0 码力 | 379 页 | 18.48 MB | 10 月前3
Hello 算法 1.0.0b4 C++版方法就是找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况。这种评估方式能够 反映真实情况,但也存在较大局限性。 难以排除测试环境的干扰因素。硬件配置会影响算法的性能表现。例如,在某台计算机中,算法 A 的运行时 间比算法 B 短;但在另一台配置不同的计算机中,我们可能得到相反的测试结果。这意味着我们需要在各种 机器上进行测试,而这是不现实的。 展开完整测试非常耗费资源。随着输入数据量的变 2.2. 时间复杂度 2.2.1. 统计算法运行时间 运行时间可以直观且准确地反映算法的效率。然而,如果我们想要准确预估一段代码的运行时间,应该如何 操作呢? 1. 确定运行平台,包括硬件配置、编程语言、系统环境等,这些因素都会影响代码的运行效率。 2. 评估各种计算操作所需的运行时间,例如加法操作 + 需要 1 ns,乘法操作 * 需要 10 ns,打印操作需要 5 ns 等。 3 Python, C++, Go, C# 等)都不支持自动优化尾递归,因此一般来说空间复杂度是 ?(?) 。 � 函数和方法这两个术语的区别是什么? 函数(function)可以独立被执行,所有参数都以显式传递。方法(method)与一个对象关 联,方法被隐式传递给调用它的对象,方法能够对类的实例中包含的数据进行操作。 因此,C 和 Go 只有函数,Java 和 C# 只有方法,在 C++0 码力 | 343 页 | 27.39 MB | 1 年前3
Hello 算法 1.0.0b1 C++版的最直接的方式,就是找一台计算机,把两个算法都完整跑一遍,并监控记录运行时间和内存占用情况。这种 评估方式能够反映真实情况,但是也存在很大的硬伤。 难以排除测试环境的干扰因素。硬件配置会影响到算法的性能表现。例如,在某台计算机中,算法 A 比算法 B 运行时间更短;但换到另一台配置不同的计算机中,可能会得到相反的测试结果。这意味着我们需要在各种机 器上展开测试,而这是不现实的。 展开完整测试非常耗费资源。随着输入数据量的大小 2. 时间复杂度 2.2.1. 统计算法运行时间 运行时间能够直观且准确地体现出算法的效率水平。如果我们想要 准确预估一段代码的运行时间,该如何做 呢? 1. 首先需要 确定运行平台,包括硬件配置、编程语言、系统环境等,这些都会影响到代码的运行效率。 2. 评估 各种计算操作的所需运行时间,例如加法操作 + 需要 1 ns ,乘法操作 * 需要 10 ns ,打印操作需要 5 ns 等。 在邻接矩阵中删除索引 index 的列 for (vector& row : adjMat) { row.erase(row.begin() + index); } } /* 添加边 */ // 参数 i, j 对应 vertices 元素索引 void addEdge(int i, int j) { // 索引越界与相等处理 if (i < 0 || j < 0 || i >= size() 0 码力 | 187 页 | 14.71 MB | 1 年前3
共 28 条
- 1
- 2
- 3













