C++高性能并行编程与优化 - 课件 - 12 从计算机组成原理看 C 语言指针移”一位,这样就不会出现 -0 这种奇怪的东西了,而且表示范围也扩大了一位,虽然是扩 大在负数部分。 有符号整数 vs 无符号整数 • 刚刚说的让 10000000 表示 -1 , 11111111 表示 -128 的方法就叫做反码表示法。 • 但是这样还有一个问题,那就是硬件电路上,需要完全重新设计,对符号位做一些特殊判 断,才能支持有符号整数的加减法,因此如今的计算机都采用了一种更聪明的表示法: • 他们让 字节内存。因此接下来的 for 循环访问了 n 个元素,实际上是访问了 n*4 个字节,会产生访 问越界现象,轻则程序直接奔溃,重则被黑客利用 来入侵系统。 如果想要的是 int 数组呢? • 解决方法是,使用 malloc(n * 4) 来分配 int 数组 ,其中 4 代表 int 类型的大小。 如果想要的是 short 数组呢? • 已知 short 的大小是 2 字节,所以用 malloc(n 实际把数据写入到你分配的数组。这样就不需要让 func 负责 malloc ,对调用者自由度更 高。 • 例子: clGetPlatformIDs , glGetProgramInfo 等专业 API 函数刻在 DNA 里的调用方法 。 错误典型:返回栈上数组的地址 • 看右边这个例子,这是我在一份看起来很 专业的 CFD 代码里看到的,真的泵不住 了。 • int a[1024] 是一个定长数组,是在栈上分 配的。而栈变量的特点是,函数0 码力 | 128 页 | 2.95 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程• 调用语法: <<>> 区分板块和线程有点麻烦?“扁平化”他们! • 你可能觉得纳闷,既然已经有线程可以并行了 ,为什么还要引入板块的概念?稍后会说明区 分板块的重要原因。 • 如需总的线程数量: blockDim * gridDim • 如需总的线程编号: blockDim * blockIdx + threadIdx • 剧透一下:实际上 语言的整数除法 n / nthreads ,他是向下取整的,比如 7 / 4 = 1 。 • 比如 n 为 65535 ,那么最后 127 个元 素是没有赋值的。 解决边角料难题 • 解决方法就是:采用向上取整的除法。 • 可是 C 语言好像没有向上整除的除法这 个运算符?没关系,用这个式子即可: • (n + nthreads - 1) / nthreads • 例如: (7 + ,也不会漏掉几个元素。 • 这样一个 for 循环非常符合 CPU 上常见的 parallel for 的习惯,又能自动匹配不同的 blockDim 和 gridDim ,看起来非常方便。 本方法出自英伟达官方博客: https://developer.nvidia.com/blog/cuda-pro-tip-write-flexible-kernels-grid-stride-loops/ 0 码力 | 142 页 | 13.52 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 14 C++ 标准库系列课 - 你所不知道的 set 容器• iterator erase(iterator pos); 1 2 3 4 5 find(4) begin() prev(end()) end() set 增删改查操作总结 操作 实现方法 增 a.insert(x) 删 a.erase(x) 或者 a.erase(a.find(x)) 改 一旦插入就无法修改,只能先删再增 查 a.find(x) != a.end() 或者 a erase(iterator first, iterator last); 1 2 3 4 5 lower_bound(2) begin() end() upper_bound(4) set 的遍历 • 遍历方法和上一课 vector 中的一样,背板即可。 • 为什么这样写呢?复习! 复习 C 语言指针( 1 ) • 上节课说了,迭代器就是在模仿 C 语言指针。 • 回想一下 C 语言咋遍历数组的: 素存在,那么 find 会返回哪 一个?第一个! • find(x) 会返回第一个等于 x 的元素的迭代器。找不到也 是返回 end() 。 multiset 增删改查操作总结 操作 实现方法 增 a.insert(x) 删 a.erase(x) 或者 a.erase(a.lower_bound(x), a.upper_bound(x)) 改 一旦插入就无法修改,只能先删再增 查0 码力 | 83 页 | 10.23 MB | 1 年前3
JVM 内存模型Native Method Stack PC Register JVM Stack Native Method Stack 程序计数器、虚拟 机栈, native 栈 为线程私有 堆为线程共享 方法区为线程共享 Eden From Survivor To Survivor 新生代 Old Space 老年代0 码力 | 1 页 | 48.42 KB | 1 年前3
C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅er ,指定区间的粒度 创建了 4 个线程 8 个任务 每个任务包含 4 个元素 tbb::auto_partitioner (默认) 自动根据 lambda 中函数的执行时间判断 采用何种分配方法。 tbb::static_partitioner 用于循环体不均匀的情况效果不好 tbb::simple_partitioner 用于循环体不均匀的情况效果很好 tbb::affinity_partitioner 陷入循环等待,而不像 mutex (操作系统提供调度)会让线程进入休眠状态的等待 。 若上锁的区域较小,可以用轻量级的 spin_mutex 。若上锁 的区域很大,则循环等待只会浪费 CPU 时间。这里锁的区 域是 std::copy ,比较大,所以 spin_mutex 效果不如 mutex 好。 加速比: 5.92 倍 还有 tbb::spin_rw_mutex 对标 std::shared_mutex0 码力 | 116 页 | 15.85 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 13 C++ STL 容器全解之 vector在构造时就初始化其中元素的值。 • 例如创建具有 6, 1, 7, 4 四个元素的 vector : • vectora = {6, 1, 7, 4}; • 和刚刚先创建再赋值的方法相比更直观。 • vector(initializer_list list); vector 容器:构造函数 • 初始化表达式的等号可以写也可以不写: • vector a 这个重 载是后置自增 p++ ,不带任何参数的 operator++() 这个重载是前置自增, 之所以这样是因为同名函数只能通过 参数列表类型来区分,这个 int 类型 参数没有任何实际意义,只是为了区 分不同的重载……编译器会在 p++ 的 时候自动改成调用 p.operator++(0) 。 vector 容器: begin • begin 可以获取指向第一个元素所在位置的迭代器。 • end 0 码力 | 90 页 | 4.93 MB | 1 年前3
谈谈MYSQL那点事128M 查询缓存区的最大长度,按照当前需求,一 倍一倍增加,本选项比较重要 sort_buffer_size 512K 128M 每个线程的排序缓存大小,一般按照内存可 以设置为 2M 以上,推荐是 16M ,该选项对 排序 order by , group by 起作用 record_buffer 128K 64M 每个进行一个顺序扫描的线程为其扫描的每 张表分配这个大小的一个缓冲区,可以设置 为 用来存放索引区块的缓存值 , 建议 128M 以上,不要大于内存的 30% read_buffer_size 128K 64M 用来做 MyISAM 表全表扫描的缓冲大 小 . 为从数据表顺序读取数据的读操 作保留的缓存区的长度 myisam_sort_buffer_size 16M 128M 设置 , 恢复 , 修改表的时候使用的缓冲 大小,值不要设的太大 服务优化 服务优化 InnoDB InnoDB 选项 innodb_buffer_pool_size 的 40-50%, 设置大 一点来避免在日志文件覆写上不必要的缓冲池刷新 行为 innodb_log_buffer_size 128K 64M 用来缓冲日志数据的缓冲区的大小 . 推荐是 8M , 官方推荐该值小于 16M ,最好是 1M-8M 之间 设计合理的数据表结构:适当的数据冗余 设计合理的数据表结构:适当的数据冗余 对数据表建立合适有效的数据库索引0 码力 | 38 页 | 2.04 MB | 1 年前3
Zadig 面向开发者的云原生 DevOps 平台易 用 性 增 强 接入:安装 10 分钟以内,成功率达 90% 集成环境:支持开发者 Remote debug 工作流:效率和性能、开发者体验提升 贡献者流程建立 开 放 社 区 搭 建 2021 年 5 月 2021 年 7 月 2021 年 9 月 2021 年 11 月 2021 年 12 月 1 个月功能改造 90% 功能实现开源 技术社区雏形搭建 2022 构建 3907 次,部署 2446 次 ,平均成功率 90% 以上 全面使用: 数字化转型助力每日上百万“如约”客户出行 关 注 Z a d i g 社 区 做硬科技和产业数字化的软件工程推手 成立于 2018 年 11 月 3 日, KodeRover 筑栈(上海)信息技术有限公司是国内在云原生 DevOps 领 域的领军企业。旗舰产品云原生0 码力 | 59 页 | 81.43 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 性能优化之无分支编程 Branchless Programming图表比较:分支 vs 无分支 分支 无分支 0 0.01 0.02 0.03 耗时(越低越好) 乱序 有序 • 传统的分支方法实现的 uppercase ,对于 排序过的数据明显比乱序时高效。 • 无分支的方法对于乱序和有序的数据一样 高效,性能吊打了传统的分支方法。 • 对于传统分支的做法,为什么排序了的更 高效?既然无分支更高效,我要怎样优化 才能让我的程序变成无分支的呢?那就来 大于(无符号) above e 等于 equal ne 不等于 not equal http://unixwiz.net/techtips/x86-jumps.html 手动进行无分支优化的方法 无分支优化:从汇编角度分析 • 发生了什么?让我们把源码和汇编逐个对应。 • x 是第一个参数(通过 edi 传入,被存入 rbp 指向的堆 栈) • 比较 x 和 0 的大小( cmp • 可以被优化成: • a + (cond) * (b - a) // 方法 1 • 或者更满足“对称强迫症”的: • (cond) * a + !(cond) * b // 方法 2 • 还有一种“摆烂”的做法: • (cond ? a : b) // 方法 3 • 三目运算符通常会变成和 if-else 一样的分 支,同样会生成条件跳转指令,理应一样0 码力 | 47 页 | 8.45 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 02 现代 C++ 入门:RAII 内存管理实际只传递了一个指针,避免了拷贝。 • 常见的有 std::vectorconst &arr 等。 • 注:有的教材喜欢这样: const Pig &pig ,仅仅是个人喜好不同,没有实际区 别。 函数参数类型优化规则:按引用还是按值? • 如果是基础类型(比如 int , float )则按值传递: • float squareRoot(float val); • 如果是原始指针(比如 0 码力 | 96 页 | 16.28 MB | 1 年前3
共 25 条
- 1
- 2
- 3













