面向亿行 C/C++ 代码的静态分析系统设计及实践-肖枭 测试更多是验证功能,很难检测编码缺陷 代码的快速变化使质量更难管 生产质量是责任 靠运维和事后复盘善后够吗? 静态分析工具:半智能的代码分析机器人 静态分析辅助代码评审 自动化工具+流程才是未来 Bug! Thx! Bug! 投入大 KPI不痛不痒 使用主体和责任主体不一致 一步登天想要终极AI 代码质量改进工具、流程落地难 Bug! No 评审流程多人督促 渐进式开启更多检查器 增量分析减少不适 • 软件工程师一天被邀请进行多次 代码评审,这些都不是他们自身 的KPI • 一旦工期紧996,人工评审容易 变成走形式 • 任务挂着还容易造成工程师焦虑 降低工程师劳动强度 大规模C/C++静态代码评审系统搭建 数千个活跃开发 的代码仓库 每天上千次代码 评审请求 平均每次代码评 审小于50分钟 • 需要编译C/C++代码0 码力 | 39 页 | 6.88 MB | 1 年前3
《深入浅出MFC》2/ev 印尼. 雅加达robin.hood@ibm.net 对您的书总是捧读再三,即使翻烂了也值得。这本深入浅出MFC,不但具有学习价值, 亦极具参考价值。 我买您的第一本书,好象是「内存管理与多任务」。还记得当时热中突破640KB 内存, 发现该书如获至宝。数月前购买了深入浅出MFC,并利用闲暇时间翻阅学习(包括如厕 时间... )。 我的学习曲线比较不同,我比较倾向于了解事情的因,而不是该如何做事情。比方说,「应 括消息的产生、获得、分派、判断、处理),以及对C++ 多态(polymorphism)的精确 体会。本章所提出的,是我对第一项必要基础的探讨,你可以从中获得关于Windows 程 序的诞生与死亡,以及多任务环境下程序之间共存的观念。至于第二项基础,将由第二章 为你夯实。 4 让我再强调一遍,本章就是我认为Windows 程序设计者一定要知道的基础知识。一个 连这些基础都不清楚的人,不能要求自己冒冒然就开始用Visual 是Windows 3.x 非强制性(non-preemptive)多任务的关键。应 用程序藉由此动作,提供了释放控制权的机会:如果消息队列上没有属于我的消息,我 就把机会让给别人。透过程序之间彼此协调让步的方式,达到多任务能力。Windows 95 和 18 19 Windows NT 具备强制性(preemptive)多任务能力,不再非靠GetMessage 释放CPU 控 制权不可,但0 码力 | 1009 页 | 11.08 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅度算法,轮换着执行着不同的线程,看起来 就好像是同时运行一样,其实每一时刻只有 一个线程在运行。目的:异步地处理多个不 同的任务,避免同步造成的阻塞。 • 并行:多核处理器,每个处理器执行一个线 程,真正的同时运行。目的:将一个任务分 派到多个核上,从而更快完成任务。 举个例子 • 并发:某互联网公司购置了一台单核处理 器的服务器,他正同时处理 4 个 HTTP 请求,如果是单线程的 上一课的案例代码:基于标准库 基于 TBB 的版本:任务组 • 用一个任务组 tbb::task_group 启动多个 任务,一个负责下载,一个负责和用户交 互。并在主线程中等待该任务组里的任务 全部执行完毕。 • 区别在于,一个任务不一定对应一个线程 ,如果任务数量超过 CPU 最大的线程数, 会由 TBB 在用户层负责调度任务运行在 多个预先分配好的线程,而不是由操作系 统负责调度线程运行在多个物理核心。 dedicated 让人咋 用? 第 4 章:任务域与嵌套 https://link.springer.com/chapter/10.1007%2F978-1-4842-4398-5_12 任务域: tbb::task_arena 任务域:指定使用 4 个线程 嵌套 for 循环 嵌套 for 循环:死锁问题 死锁问题的原因 • 因为 TBB 用了工作窃取法来分配任务: 当一个线程 t1 做完自己队列里全部的工0 码力 | 116 页 | 15.85 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 性能优化之无分支编程 Branchless Programming(pipeline) 。流水线的目的是能把原本 串行的一系列指令并行化。为了理解为什 么需要流水线,我们先反过来,假设没有 流水线,会有什么坏处。 • 例如,右边你今天早上的任务清单。 • 请问你这些任务总共需要多少时间? 任务 时间 占用资源 洗脸 5 分钟 眼睛,嘴巴,手 烧开水 10 分钟 煤气灶 刷牙 5 分钟 嘴巴,手 看比站 15 分钟 眼睛 吃饭 30 分钟 嘴巴,手 拉粑粑 存器来指令解码单元才开始继续工作,很 低效。 任务 时间 占用资源 洗脸 5 分钟 眼睛,嘴巴,手 烧开水 10 分钟 煤气灶 刷牙 5 分钟 嘴巴,手 看比站 15 分钟 眼睛 吃饭 30 分钟 嘴巴,手 拉粑粑 20 分钟 屁股 洗脸 烧开水 刷牙 看比站 吃饭 拉粑粑 5 10 5 15 30 20 为什么需要流水线 • 更高效的办法是,观察每个任务都占用哪些 资源,所占用资源不冲突的可以同时进行, + 20 = 40 分钟,比你快一倍多。 任务 时间 占用资源 洗脸 5 分钟 眼睛,嘴巴,手 烧开水 10 分钟 煤气灶 刷牙 5 分钟 嘴巴,手 看比站 15 分钟 眼睛 吃饭 30 分钟 嘴巴,手 拉粑粑 20 分钟 屁股 洗脸 刷牙 烧开水 吃饭 看比站 拉粑粑 5 5 10 20 条件跳转指令 • 让不占用相同资源的任务同时进行,这也是 CPU 流水线的初衷。但理想是美好的,现实0 码力 | 47 页 | 8.45 MB | 1 年前3
Hello 算法 1.1.0 C++ 版能够完成简单算 法的复杂度分析。 2.2 迭代与递归 在算法中,重复执行某个任务是很常见的,它与复杂度分析息息相关。因此,在介绍时间复杂度和空间复杂 度之前,我们先来了解如何在程序中实现重复执行任务,即两种基本的程序控制结构:迭代、递归。 2.2.1 迭代 迭代(iteration)是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某段 代码,直到这个条件不再满足。 求和函数的递归过程 虽然从计算角度看,迭代与递归可以得到相同的结果,但它们代表了两种完全不同的思考和解决问题的范 式。 ‧ 迭代:“自下而上”地解决问题。从最基础的步骤开始,然后不断重复或累加这些步骤,直到任务完成。 ‧ 递归:“自上而下”地解决问题。将原问题分解为更小的子问题,这些子问题和原问题具有相同的形式。 接下来将子问题继续分解为更小的子问题,直到基本情况时停止(基本情况的解是已知的)。 以上述求和函数为例,设问题 函数调用自身 时间效 率 效率通常较高,无函数调用开销 每次函数调用都会产生开销 内存使 用 通常使用固定大小的内存空间 累积函数调用可能使用大量的栈帧空间 适用问 题 适用于简单循环任务,代码直观、可读性 好 适用于子问题分解,如树、图、分治、回溯等,代码结构简洁、 清晰 Tip 如果感觉以下内容理解困难,可以在读完“栈”章节后再来复习。 那么,迭代和递归具有什么内在联0 码力 | 379 页 | 18.47 MB | 1 年前3
Hello 算法 1.0.0 C++版够完成简单算 法的复杂度分析。 2.2 迭代与递归 在算法中,重复执行某个任务是很常见的,它与复杂度分析息息相关。因此,在介绍时间复杂度和空间复杂 度之前,我们先来了解如何在程序中实现重复执行任务,即两种基本的程序控制结构:迭代、递归。 2.2.1 迭代 「迭代 iteration」是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某 段代码,直到这个条件不再满足。 求和函数的递归过程 虽然从计算角度看,迭代与递归可以得到相同的结果,但它们代表了两种完全不同的思考和解决问题的范 式。 ‧ 迭代:“自下而上”地解决问题。从最基础的步骤开始,然后不断重复或累加这些步骤,直到任务完成。 ‧ 递归:“自上而下”地解决问题。将原问题分解为更小的子问题,这些子问题和原问题具有相同的形式。 接下来将子问题继续分解为更小的子问题,直到基本情况时停止(基本情况的解是已知的)。 以上述求和函数为例,设问题 函数调用自身 时间效 率 效率通常较高,无函数调用开销 每次函数调用都会产生开销 内存使 用 通常使用固定大小的内存空间 累积函数调用可能使用大量的栈帧空间 适用问 题 适用于简单循环任务,代码直观、可读性 好 适用于子问题分解,如树、图、分治、回溯等,代码结构简洁、 清晰 � 如果感觉以下内容理解困难,可以在读完“栈”章节后再来复习。 那么,迭代和递归具有什么内在联系呢0 码力 | 378 页 | 17.59 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程1>>>() 后,并不 会立即在 GPU 上执行完毕,再返回。实际上只是把 kernel 这个任务推送到 GPU 的执行队列上,然后立即 返回,并不会等待执行完毕。 • 因此可以调用 cudaDeviceSynchronize() ,让 CPU 陷 入等待,等 GPU 完成队列的所有任务后再返回。从而 能够在 main 退出前等到 kernel 在 GPU 上执行完。 定义在 GPU 当前板块的编号: blockIdx • 总的板块数量: gridDim • 线程 (thread) :并行的最小单位 • 板块 (block) :包含若干个线程 • 网格 (grid) :指整个任务,包含若干个板块 • 从属关系:线程<板块<网格 • 调用语法: <<>> 区分板块和线程有点麻烦?“扁平化”他们! • 你可能觉得纳闷,既然已经有线程可以并行了 稍微快一些,但不完全精确的 __sinf • 两个下划线的 __sinf 是 GPU intrinstics ,精度相当于 GLSL 里的那种。 适合对精度要求不高,但有性能要求的图 形学任务。 • 类似的这样的低精度內建函数还有 __expf 、 __logf 、 __cosf 、 __powf 等。 • 还有 __fdividef(x, y) 提供更快的浮点除法 ,和一般的除法有相同的精确度,但是在 0 码力 | 142 页 | 13.52 MB | 1 年前3
Hello 算法 1.0.0b5 C++版步的了解,以便能够完成简单算 法的复杂度分析。 2.2 迭代与递归 在数据结构与算法中,重复执行某个任务是很常见的,其与算法的复杂度密切相关。而要重复执行某个任务, 我们通常会选用两种基本的程序结构:迭代和递归。 2.2.1 迭代 「迭代 iteration」是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某 段代码,直到这个条件不再满足。 1. for 求和函数的递归过程 虽然从计算角度看,迭代与递归可以得到相同的结果,但它们代表了两种完全不同的思考和解决问题的范 式。 ‧ 迭代:“自下而上”地解决问题。从最基础的步骤开始,然后不断重复或累加这些步骤,直到任务完成。 ‧ 递归:“自上而下”地解决问题。将原问题分解为更小的子问题,这些子问题和原问题具有相同的形式。 接下来将子问题继续分解为更小的子问题,直到基本情况时停止(基本情况的解是已知的)。 以上述的求和函数为例,设问题 最差、最佳、平均时间复杂度 算法的时间效率往往不是固定的,而是与输入数据的分布有关。假设输入一个长度为 ? 的数组 nums ,其中 nums 由从 1 至 ? 的数字组成,每个数字只出现一次;但元素顺序是随机打乱的,任务目标是返回元素 1 的 索引。我们可以得出以下结论。 ‧ 当 nums = [?, ?, ..., 1] ,即当末尾元素是 1 时,需要完整遍历数组,达到最差时间复杂度 ?(?) 。 ‧ 当 nums0 码力 | 377 页 | 30.69 MB | 1 年前3
Hello 算法 1.2.0 简体中文 C++ 版能够完成简单算 法的复杂度分析。 2.2 迭代与递归 在算法中,重复执行某个任务是很常见的,它与复杂度分析息息相关。因此,在介绍时间复杂度和空间复杂 度之前,我们先来了解如何在程序中实现重复执行任务,即两种基本的程序控制结构:迭代、递归。 2.2.1 迭代 迭代(iteration)是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某段 代码,直到这个条件不再满足。 求和函数的递归过程 虽然从计算角度看,迭代与递归可以得到相同的结果,但它们代表了两种完全不同的思考和解决问题的范 式。 ‧ 迭代:“自下而上”地解决问题。从最基础的步骤开始,然后不断重复或累加这些步骤,直到任务完成。 ‧ 递归:“自上而下”地解决问题。将原问题分解为更小的子问题,这些子问题和原问题具有相同的形式。 接下来将子问题继续分解为更小的子问题,直到基本情况时停止(基本情况的解是已知的)。 以上述求和函数为例,设问题 函数调用自身 时间效 率 效率通常较高,无函数调用开销 每次函数调用都会产生开销 内存使 用 通常使用固定大小的内存空间 累积函数调用可能使用大量的栈帧空间 适用问 题 适用于简单循环任务,代码直观、可读性 好 适用于子问题分解,如树、图、分治、回溯等,代码结构简洁、 清晰 Tip 如果感觉以下内容理解困难,可以在读完“栈”章节后再来复习。 那么,迭代和递归具有什么内在联0 码力 | 379 页 | 18.48 MB | 10 月前3
Hello 算法 1.0.0b4 C++版最差、最佳、平均时间复杂度 某些算法的时间复杂度不是固定的,而是与输入数据的分布有关。例如,假设输入一个长度为 ? 的数组 nums ,其中 nums 由从 1 至 ? 的数字组成,但元素顺序是随机打乱的;算法的任务是返回元素 1 的索引。我们可 以得出以下结论: ‧ 当 nums = [?, ?, ..., 1] ,即当末尾元素是 1 时,需要完整遍历数组,此时达到 最差时间复杂度 ?(?) 。 ‧ 当 nums 一 期间,短时间内会产生海量订单,高并发成为工程师们需要重点攻克的问题。 5. 栈与队列 hello‑algo.com 81 ‧ 各类待办事项。任何需要实现“先来后到”功能的场景,例如打印机的任务队列、餐厅的出餐队列等。 队列在这些场景中可以有效地维护处理顺序。 5.3. 双向队列 对于队列,我们仅能在头部删除或在尾部添加元素。然而,「双向队列 Deque」提供了更高的灵活性,允许 在头部和尾部执行元素的添加或删除操作。 时,我们可以得到从大到小的序列,等价于「选择排序」算法。 8.3.2. 方法二:排序 我们可以对数组 nums 进行排序,并返回最右边的 ? 个元素,时间复杂度为 ?(? log ?) 。 显然,该方法“超额”完成任务了,因为我们只需要找出最大的 ? 个元素即可,而不需要排序其他元素。 Figure 8‑7. 排序寻找最大的 k 个元素 8.3.3. 方法三:堆 我们可以基于堆更加高效地解决 Top‑K 问题,流程如下:0 码力 | 343 页 | 27.39 MB | 1 年前3
共 16 条
- 1
- 2













