《深入浅出MFC》2/eWorker Thread / 759 產生㆒個 UI Thread / 761 執行緒的結束 / 763 執行緒與同步控制 / 763 MFC 多緒程式實例 / 766 目 錄 25 * 第 15 章 定製㆒個 AppWizard / 771 到底 Wizard 是什麼? / C++ 类別) window focus 窗口焦点(拥有焦点之窗口,将可获得键盘输入) 以下是本书使用之中英文名词对照表: 控制组件,如 拖放(鼠标左键按下,选中图标后拖动,然后放开) 图标(窗口缩小化后的小图样) 串行 列表框、列表清单 通告消息(发生于控制组件) 强制性、先占式、优先权式 进程(一个执行起来的程序) 队列 template C++ 有所谓的class template,一般译为类别模板; d 增设对 话盒处理函数,以及如何以MFC 提供的DDX/DDV 机制做出对话框控制组件 (control)的内容传递与内容查核。DDX(Dialog Data eXchange)的目的在简化应用 程序取得控制组件内容的过程,DDV(Dialog Data Validation)的目的则在加强应用 程序对控制组件内容之数值合理化检查。 Scribble Step4-加强显示能力- 滚动条与分裂窗口(第110 码力 | 1009 页 | 11.08 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 07 深入浅出访存优化通常来说,并行只能加速计算的部分,不能加速内存读写的部分 。 • 因此,对 fill 这种没有任何计算量,纯粹只有访存的循环体,并 行没有加速效果。称为内存瓶颈( memory-bound )。 • 而 sine 这种内部需要泰勒展开来计算,每次迭代计算量很大的 循环体,并行才有较好的加速效果。称为计算瓶颈( cpu- bound )。 • 并行能减轻计算瓶颈,但不减轻内存瓶颈,故后者是优化的重点 1024 并非随意选取,而是要让每 个属性 SOA 数组的大小为一个页 ( 4KB )才能最高效,原因稍后会说明。 AOSOA :注意,内部 SOA 的尺寸不宜太小 如果内部 SOA 太小,内部循环只有 16 次连续的读 取, 16 次结束后就会跳跃一段,然后继续连续的 读取。这会导致 CPU 预取机制失效,无法预测下 一次要读哪里,等发现跳跃时已经来不及了,从而 计算的延迟无法隐藏。 如果每个属性都要访问到,那还是 解的伪代码,延迟和花费的时钟周期等。 第 4 章:循环合并法 两个循环体 • 原始的代码第一个循环体执行 a[i] = a[i] * 2 ,等乘法全 部结束了以后,再来一个循环体执行 a[i] = a[i] + 1 。 • 因为第一遍循环过了 1GB 的数据,执行到 a[n-1] 时 ,原本 a[0] 处的缓存早已失效,因此第二遍循环开始 读取 a[0] 时必须重新从主内存读取,然后再次写回主0 码力 | 147 页 | 18.88 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 02 现代 C++ 入门:RAII 内存管理// 拷贝赋值 • 追求性能时推荐用拷贝构造,因为可以避免一次无参构造,拷贝赋值是出于需要临时修改 对象的灵活性需要。 • 这个函数同样可以由 = delete 和 = default 控制是否默认生成。 • 注: return *this 是为了支持连等号 a = b = c; 编译器自动生成的函数:全家桶 • 其实,除了拷贝构造和拷贝赋值,编译器会自动生成的特殊函数还有这些: 请根据你的具体情况,决定要选用哪一种 解决方案。 移交控制权后仍希望访问到 p 指向的对象 • 解决方案 2 中,有时候我们会遇到移交控 制权后,仍希望访问到对象的需求。 • 如果还是用 p 去访问的话,因为被移动构 造函数转移了, p 已经变成空指针,从而 出错。 解决方案:提前获取原始指针 • 最简单的办法是,在移交控制权给 func 前,提前通过 p.get() 获取原始指针: 效率低,需要额外的一块管理内存,访问实际对象 需要二级指针,而且 deleter 使用了类型擦除技术 。 2. 全部用 shared_ptr ,可能出现循环引用之类的问题 ,导致内存泄露,依然需要使用不影响计数的原始 指针或者 weak_ptr 来避免。比如右边这个例子: 循环引用:解决方案 1 • 如何解决?只需要把其中逻辑上“不具有所 属权”的那一个改成 weak_ptr 即可: • 因为父窗口“拥有”子窗口是天经地义的,而0 码力 | 96 页 | 16.28 MB | 1 年前3
Hello 算法 1.1.0 C++ 版1. 将扑克牌划分为“有序”和“无序”两部分,并假设初始状态下最左 1 张扑克牌已经有序。 2. 在无序部分抽出一张扑克牌,插入至有序部分的正确位置;完成后最左 2 张扑克已经有序。 3. 不断循环步骤 2. ,每一轮将一张扑克牌从无序部分插入至有序部分,直至所有扑克牌都有序。 图 1‑2 扑克排序步骤 上述整理扑克牌的方法本质上是“插入排序”算法,它在处理小型数据集时非常高效。许多编程语言的排序 度之前,我们先来了解如何在程序中实现重复执行任务,即两种基本的程序控制结构:迭代、递归。 2.2.1 迭代 迭代(iteration)是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某段 代码,直到这个条件不再满足。 1. for 循环 for 循环是最常见的迭代形式之一,适合在预先知道迭代次数时使用。 以下函数基于 for 循环实现了求和 1 + 2 + ⋯ + ? ,求和结果使用变量 对应的区间是“左闭右开”的,对应的遍历范围为 ?, ? + 1, … , ? − 1 : // === File: iteration.cpp === /* for 循环 */ int forLoop(int n) { int res = 0; // 循环求和 1, 2, ..., n-1, n for (int i = 1; i <= n; ++i) { res += i; } return res;0 码力 | 379 页 | 18.47 MB | 1 年前3
Hello 算法 1.0.0 C++版1. 将扑克牌划分为“有序”和“无序”两部分,并假设初始状态下最左 1 张扑克牌已经有序。 2. 在无序部分抽出一张扑克牌,插入至有序部分的正确位置;完成后最左 2 张扑克已经有序。 3. 不断循环步骤 2. ,每一轮将一张扑克牌从无序部分插入至有序部分,直至所有扑克牌都有序。 图 1‑2 扑克排序步骤 上述整理扑克牌的方法本质上是“插入排序”算法,它在处理小型数据集时非常高效。许多编程语言的排序 度之前,我们先来了解如何在程序中实现重复执行任务,即两种基本的程序控制结构:迭代、递归。 2.2.1 迭代 「迭代 iteration」是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某 段代码,直到这个条件不再满足。 1. for 循环 for 循环是最常见的迭代形式之一,适合在预先知道迭代次数时使用。 以下函数基于 for 循环实现了求和 1 + 2 + ⋯ + ? ,求和结果使用变量 对应的区间是“左闭右开”的,对应的遍历范围为 ?, ? + 1, … , ? − 1 : // === File: iteration.cpp === /* for 循环 */ int forLoop(int n) { int res = 0; // 循环求和 1, 2, ..., n-1, n for (int i = 1; i <= n; ++i) { res += i; } return res;0 码力 | 378 页 | 17.59 MB | 1 年前3
Hello 算法 1.2.0 简体中文 C++ 版1. 将扑克牌划分为“有序”和“无序”两部分,并假设初始状态下最左 1 张扑克牌已经有序。 2. 在无序部分抽出一张扑克牌,插入至有序部分的正确位置;完成后最左 2 张扑克已经有序。 3. 不断循环步骤 2. ,每一轮将一张扑克牌从无序部分插入至有序部分,直至所有扑克牌都有序。 图 1‑2 扑克排序步骤 上述整理扑克牌的方法本质上是“插入排序”算法,它在处理小型数据集时非常高效。许多编程语言的排序 度之前,我们先来了解如何在程序中实现重复执行任务,即两种基本的程序控制结构:迭代、递归。 2.2.1 迭代 迭代(iteration)是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某段 代码,直到这个条件不再满足。 1. for 循环 for 循环是最常见的迭代形式之一,适合在预先知道迭代次数时使用。 以下函数基于 for 循环实现了求和 1 + 2 + ⋯ + ? ,求和结果使用变量 对应的区间是“左闭右开”的,对应的遍历范围为 ?, ? + 1, … , ? − 1 : // === File: iteration.cpp === /* for 循环 */ int forLoop(int n) { int res = 0; // 循环求和 1, 2, ..., n-1, n for (int i = 1; i <= n; ++i) { res += i; } return res;0 码力 | 379 页 | 18.48 MB | 10 月前3
Hello 算法 1.0.0b5 C++版1. 将扑克牌划分为“有序”和“无序”两部分,并假设初始状态下最左 1 张扑克牌已经有序。 2. 在无序部分抽出一张扑克牌,插入至有序部分的正确位置;完成后最左 2 张扑克已经有序。 3. 不断循环步骤 2. ,每一轮将一张扑克牌从无序部分插入至有序部分,直至所有扑克牌都有序。 图 1‑2 扑克排序步骤 上述整理扑克牌的方法本质上是“插入排序”算法,它在处理小型数据集时非常高效。许多编程语言的排序 我们通常会选用两种基本的程序结构:迭代和递归。 2.2.1 迭代 「迭代 iteration」是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某 段代码,直到这个条件不再满足。 1. for 循环 for 循环是最常见的迭代形式之一,适合预先知道迭代次数时使用。 以下函数基于 for 循环实现了求和 1 + 2 + ⋯ + ? ,求和结果使用变量 res 记录。需要注意的是,Python 对应的区间是“左闭右开”的,对应的遍历范围为 ?, ? + 1, … , ? − 1 。 // === File: iteration.cpp === /* for 循环 */ int forLoop(int n) { int res = 0; // 循环求和 1, 2, ..., n-1, n for (int i = 1; i <= n; ++i) { res += i; } return res;0 码力 | 377 页 | 30.69 MB | 1 年前3
现代C++ 教程:高速上手C++11/14/17/20decltype(auto) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.4 控制流 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 GCC/Clang 等编译器中的支持情况 • C++98 与 C99 之间的区别 11 第 2 章语言可用性的强化 第 2 章语言可用性的强化 当我们声明、定义一个变量或者常量,对代码进行流程控制、面向对象的功能、模板编程等这些都 是运行时之前,可能发生在编写代码或编译器编译代码时的行为。为此,我们通常谈及语言可用性,是 指那些发生在运行时之前的语言行为。 2.1 常量 nullptr fibonacci(n-1)+fibonacci(n-2); } 14 2.2 变量及其初始化 第 2 章语言可用性的强化 从 C++14 开始,constexpr 函数可以在内部使用局部变量、循环和分支等简单语句,例如下面的 代码在 C++11 的标准下是不能够通过编译的: constexpr int fibonacci(const int n) { if(n == 1) return0 码力 | 83 页 | 2.42 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅程,真正的同时运行。目的:将一个任务分 派到多个核上,从而更快完成任务。 举个例子 • 并发:某互联网公司购置了一台单核处理 器的服务器,他正同时处理 4 个 HTTP 请求,如果是单线程的 listen-accept 循环 ,则在处理完 A 的请求之前, B 的请求 就无法处理,造成“无响应”现象。 C 的请 求进来,则还得继续排队…… • 每个请求开启一个线程来处理,这样处理 A 用户的同时还可以继续监听 会由 TBB 在用户层负责调度任务运行在 多个预先分配好的线程,而不是由操作系 统负责调度线程运行在多个物理核心。 封装好了: parallel_invoke 更好的例子 第 1 章:并行循环 时间复杂度( time-efficiency )与工作量复杂度( work-efficiency ) • 在“小学二年级”算法课里,我们学过复杂度的概念,意思是算法执行所花费的时间取决于数据量 是线程数量 封装好了: parallel_for 面向初学者: parallel_for 基于迭代器区间: parallel_for_each 二维区间上的 for 循环: blocked_range2d 三维区间上的 for 循环: blocked_range3d 所有区间类型 第 2 章:缩并与扫描 缩并( reduce ) 1 个线程,依次处理 8 个元素的缩并,花了 7 秒 用电量:0 码力 | 116 页 | 15.85 MB | 1 年前3
Hello 算法 1.0.0b4 C++版2. 在无序区间抽出一张扑克牌,插入至有序区间的正确位置;完成后最左 2 张扑克已经有序。 3. 在无序区间抽出一张扑克牌,插入至有序区间的正确位置;完成后最左 3 张扑克已经有序。 4. 不断循环以上操作,直至所有扑克牌都有序后终止。 以上整理扑克牌的方法本质上就是「插入排序」算法,它在处理小型数据集时非常高效。许多编程语言的排 序库函数中都存在插入排序的身影。 Figure 1‑2. // 在某运行平台下 void algorithm(int n) { int a = 2; // 1 ns a = a + 1; // 1 ns a = a * 2; // 10 ns // 循环 n 次 for (int i = 0; i < n; i++) { // 1 ns ,每轮都要执行 i++ cout << 0 << endl; // 5 ns } } 2. 复杂度 hello‑algo 只有 1 个打印操作,算法运行时间不随着 ? 增大而增长。我们称此算法的时间复杂度为「常数 阶」。 ‧ 算法 B 中的打印操作需要循环 ? 次,算法运行时间随着 ? 增大呈线性增长。此算法的时间复杂度被称 为「线性阶」。 ‧ 算法 C 中的打印操作需要循环 1000000 次,但运行时间仍与输入数据大小 ? 无关。因此 C 的时间复杂 度和 A 相同,仍为「常数阶」。 // 算法 A 时间复杂度:常数阶0 码力 | 343 页 | 27.39 MB | 1 年前3
共 28 条
- 1
- 2
- 3













