C++高性能并行编程与优化 - 课件 - 12 从计算机组成原理看 C 语言指针
数据删除 ] 嘛。 有符号整数 vs 无符号整数 • 有时候我们是需要表示负数的。而刚刚那种二进制的做法,只能表示正数和零。 • 怎么办?可能有的同学会想,不妨这样来设计:让二进制的最高位表示符号位。 • 比如 00000011 表示 3 , 10000011 表示 -3 ,这样不就区分开来了吗?这叫做原码表示 法。 • 的确可以,这种表示方式牺牲了一位作为符号位,剩下 7 位继续表示值。 位继续表示值。 • 这样的设计下无符号可以表示 0 到 255 ,而有符号可以表示 -127 到 127 。 • 但是有一个问题,那 00000000 就表示 0 , 10000000 就表示 -0 ,而 0 有没有负号其 实无所谓, 0 和 -0 根本是同一个数,却有着不同的表示,这显然不对吧? • 因此,可以如 10000000 实际上表示 -1 , 11111111 则表示 -128 ,让负数部分整体“平 -0 这种奇怪的东西了,而且表示范围也扩大了一位,虽然是扩 大在负数部分。 有符号整数 vs 无符号整数 • 刚刚说的让 10000000 表示 -1 , 11111111 表示 -128 的方法就叫做反码表示法。 • 但是这样还有一个问题,那就是硬件电路上,需要完全重新设计,对符号位做一些特殊判 断,才能支持有符号整数的加减法,因此如今的计算机都采用了一种更聪明的表示法: • 他们让 111111110 码力 | 128 页 | 2.95 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 15 C++ 系列课:字符与字符串
org/wiki/ASCII 计算机如何表达字符 • 众所周知,计算机只能处理二进制 整数,字符要怎么办呢? • 于是就有了 ASCII 码表,他规定, 每个英文字符(包括大小写字母、 数字、特殊符号)都对应着一个整 数。在计算机里只要存储这个的整 数,就能代表这个字符了。 • 例如 32 代表空格, 48 代表 ‘ 0’ , 65 代表 ‘ A’ , 97 代表 ‘ a’…… • 32~126 char 是无符号 8 位整数, signed char 是有 符号 8 位整数,而 char 类型只需是 8 位整数即可,可以是有符号也可以 是无符号,任凭编译器决定( C 标准委员会传统异能, khronos 直呼内行) 。 • 以 GCC 为例,他规定 char 在 x86 架构是有符号的 (char = signed char) ,而在 arm 架构上则认为是无符号的 (char = = unsigned char) ,因为他 认为“ arm 的指令集处理无符号 8 位整数更高效”,所以擅自把 char 魔改成无 符号的…… • 顺便一提, C++ 标准保证 char , signed char , unsigned char 是三个完全 不同的类型, std::is_same_v 分别判断他们总会得到 false ,无论 x86 还是 arm 。 • 但是奇葩的 C 语言却规定0 码力 | 162 页 | 40.20 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 性能优化之无分支编程 Branchless Programming
含义 英文全称 le 小于等于(有符号) less or equal ge 大于等于(有符号) greater or equal l 小于(有符号) less g 大于(有符号) greater be 小于等于(无符号) below or equal ae 大于等于(无符号) above or equal b 小于(无符号) below a 大于(无符号) above e 等于 equal0 码力 | 47 页 | 8.45 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 10 从稀疏数据结构到量化数据类型
如果 b 是常数且为 2 的幂次方,编译器会检测到, 并替换为更高效的位运算,反而减少了计算量。 • 此外如果 b 一定是 2 的幂次方,那么 (unsigned)a % b 也可以(先转换成无符号的取模)。 高效的解决:位运算 & • 如果 b 是 2 的幂次方,即: 2, 4, 8, 16, 32 等 。 • 则: a % b = a & (b - 1) • 比如 a % 8 可以改成 Python 一样的始终向下取整除 法。 >> 2 = unsigned 类型的位运算 >> 不一样 而 unsigned 类型的 >> n 会不会复制最高位, 只是单纯的位移,这会导致负数的符号位单独被位 移,补码失效,造成结果不对。 unsigned 类型的 >> 会生成 shr 指令, signed 类型的 >> 会生成 sar 指令。 我们需要负方向无限延伸的稀疏数据结果,那就只 pointer(11).dense(8) 开源的体素处理库: OpenVDB • OpenVDB 的稀疏体积,可以存储符号距 离场 (SDF) ,也可以存储烟雾仿真的结果 等。 • 据张心欣说, OpenVDB 赢得了奥斯卡奖 。 • 因为他经常用在影视特效中,主要是符号 距离场有时比 mesh 处理起来方便很多。 OpenVDB 的设计:如果用 SNode 来表示 • hash()0 码力 | 102 页 | 9.50 MB | 1 年前3Hello 算法 1.1.0 C++ 版
,则以上函数的操作数量为: ?(?) = 3 + 2? ?(?) 是一次函数,说明其运行时间的增长趋势是线性的,因此它的时间复杂度是线性阶。 我们将线性阶的时间复杂度记为 ?(?) ,这个数学符号称为大 ? 记号(big‑? notation),表示函数 ?(?) 的 渐近上界(asymptotic upper bound)。 时间复杂度分析本质上是计算“操作数量 ?(?)”的渐近上界,它具有明确的数学定义。 但对于较为复杂的算法,计算平均时间复杂度往往比较困难,因为很难分析出在数据分布下的整体数学期望。 在这种情况下,我们通常使用最差时间复杂度作为算法效率的评判标准。 为什么很少看到 Θ 符号? 可能由于 ? 符号过于朗朗上口,因此我们常常使用它来表示平均时间复杂度。但从严格意义上讲,这 种做法并不规范。在本书和其他资料中,若遇到类似“平均时间复杂度 ?(?)”的表述,请将其直接 理解为 Θ( 时间复杂度用于衡量算法运行时间随数据量增长的趋势,可以有效评估算法效率,但在某些情况下可 能失效,如在输入的数据量较小或时间复杂度相同时,无法精确对比算法效率的优劣。 ‧ 最差时间复杂度使用大 ? 符号表示,对应函数渐近上界,反映当 ? 趋向正无穷时,操作数量 ?(?) 的 增长级别。 ‧ 推算时间复杂度分为两步,首先统计操作数量,然后判断渐近上界。 ‧ 常见时间复杂度从低到高排列有 ?(1)、0 码力 | 379 页 | 18.47 MB | 1 年前3Hello 算法 1.0.0 C++版
,则以上函数的操作数量为: ?(?) = 3 + 2? ?(?) 是一次函数,说明其运行时间的增长趋势是线性的,因此它的时间复杂度是线性阶。 我们将线性阶的时间复杂度记为 ?(?) ,这个数学符号称为「大 ? 记号 big‑? notation」,表示函数 ?(?) 的「渐近上界 asymptotic upper bound」。 时间复杂度分析本质上是计算“操作数量 ?(?)”的渐近上界,它具有明确的数学定义。 但对于较为复杂的算法,计算平均时间复杂度往往比较困难,因为很难分析出在数据分布下的整体数学期望。 在这种情况下,我们通常使用最差时间复杂度作为算法效率的评判标准。 � 为什么很少看到 Θ 符号? 可能由于 ? 符号过于朗朗上口,因此我们常常使用它来表示平均时间复杂度。但从严格意义 上讲,这种做法并不规范。在本书和其他资料中,若遇到类似“平均时间复杂度 ?(?)”的表 述,请将其直接理解为 Θ( 时间复杂度用于衡量算法运行时间随数据量增长的趋势,可以有效评估算法效率,但在某些情况下可 能失效,如在输入的数据量较小或时间复杂度相同时,无法精确对比算法效率的优劣。 ‧ 最差时间复杂度使用大 ? 符号表示,对应函数渐近上界,反映当 ? 趋向正无穷时,操作数量 ?(?) 的 增长级别。 ‧ 推算时间复杂度分为两步,首先统计操作数量,然后判断渐近上界。 ‧ 常见时间复杂度从低到高排列有 ?(1)、0 码力 | 378 页 | 17.59 MB | 1 年前3Hello 算法 1.2.0 简体中文 C++ 版
,则以上函数的操作数量为: ?(?) = 3 + 2? ?(?) 是一次函数,说明其运行时间的增长趋势是线性的,因此它的时间复杂度是线性阶。 我们将线性阶的时间复杂度记为 ?(?) ,这个数学符号称为大 ? 记号(big‑? notation),表示函数 ?(?) 的 渐近上界(asymptotic upper bound)。 时间复杂度分析本质上是计算“操作数量 ?(?)”的渐近上界,它具有明确的数学定义。 但对于较为复杂的算法,计算平均时间复杂度往往比较困难,因为很难分析出在数据分布下的整体数学期望。 在这种情况下,我们通常使用最差时间复杂度作为算法效率的评判标准。 为什么很少看到 Θ 符号? 可能由于 ? 符号过于朗朗上口,因此我们常常使用它来表示平均时间复杂度。但从严格意义上讲,这 种做法并不规范。在本书和其他资料中,若遇到类似“平均时间复杂度 ?(?)”的表述,请将其直接 理解为 Θ( 时间复杂度用于衡量算法运行时间随数据量增长的趋势,可以有效评估算法效率,但在某些情况下可 能失效,如在输入的数据量较小或时间复杂度相同时,无法精确对比算法效率的优劣。 ‧ 最差时间复杂度使用大 ? 符号表示,对应函数渐近上界,反映当 ? 趋向正无穷时,操作数量 ?(?) 的 增长级别。 ‧ 推算时间复杂度分为两步,首先统计操作数量,然后判断渐近上界。 ‧ 常见时间复杂度从低到高排列有 ?(1)、0 码力 | 379 页 | 18.48 MB | 10 月前3Hello 算法 1.0.0b4 C++版
2. 复杂度 hello‑algo.com 17 } } ?(?) 是一次函数,说明时间增长趋势是线性的,因此可以得出时间复杂度是线性阶。 我们将线性阶的时间复杂度记为 ?(?) ,这个数学符号称为「大 ? 记号 Big‑? Notation」,表示函数 ?(?) 的「渐近上界 Asymptotic Upper Bound」。 推算时间复杂度本质上是计算“操作数量函数 ?(?)”的渐近 但在实际应用中,尤其是较为复杂的算法,计算平均时间复杂度比较困难,因为很难简便地分析出在数据分 布下的整体数学期望。在这种情况下,我们通常使用最差时间复杂度作为算法效率的评判标准。 � 为什么很少看到 Θ 符号? 可能由于 ? 符号过于朗朗上口,我们常常使用它来表示「平均复杂度」,但从严格意义上看, 这种做法并不规范。在本书和其他资料中,若遇到类似“平均时间复杂度 ?(?)”的表述,请 将其直接理解为 Θ(?) 时间复杂度用于衡量算法运行时间随数据量增长的趋势,可以有效评估算法效率,但在某些情况下可 能失效,如在输入数据量较小或时间复杂度相同时,无法精确对比算法效率的优劣。 ‧ 最差时间复杂度使用大 ? 符号表示,即函数渐近上界,反映当 ? 趋向正无穷时,?(?) 的增长级别。 ‧ 推算时间复杂度分为两步,首先统计计算操作数量,然后判断渐近上界。 ‧ 常见时间复杂度从小到大排列有 ?(1) , ?(log0 码力 | 343 页 | 27.39 MB | 1 年前3Hello 算法 1.0.0b5 C++版
,则以上函数的的操作数量为: ?(?) = 3 + 2? ?(?) 是一次函数,说明其运行时间的增长趋势是线性的,因此它的时间复杂度是线性阶。 我们将线性阶的时间复杂度记为 ?(?) ,这个数学符号称为「大 ? 记号 big‑? notation」,表示函数 ?(?) 的「渐近上界 asymptotic upper bound」。 时间复杂度分析本质上是计算“操作数量函数 ?(?)”的渐近上界,其具有明确的数学定义。 但对于较为复杂的算法,计算平均时间复杂度往往是比较困难的,因为很难分析出在数据分布下的整体数学 期望。在这种情况下,我们通常使用最差时间复杂度作为算法效率的评判标准。 � 为什么很少看到 Θ 符号? 可能由于 ? 符号过于朗朗上口,我们常常使用它来表示平均时间复杂度。但从严格意义上看, 这种做法并不规范。在本书和其他资料中,若遇到类似“平均时间复杂度 ?(?)”的表述,请 将其直接理解为 Θ(?) 时间复杂度用于衡量算法运行时间随数据量增长的趋势,可以有效评估算法效率,但在某些情况下可 能失效,如在输入的数据量较小或时间复杂度相同时,无法精确对比算法效率的优劣。 ‧ 最差时间复杂度使用大 ? 符号表示,对应函数渐近上界,反映当 ? 趋向正无穷时,操作数量 ?(?) 的 增长级别。 ‧ 推算时间复杂度分为两步,首先统计操作数量,然后判断渐近上界。 ‧ 常见时间复杂度从小到大排列有 ?(1)、0 码力 | 377 页 | 30.69 MB | 1 年前3Hello 算法 1.0.0b1 C++版
cout << 0 << endl; // +1 } } ?(?) 是个一次函数,说明时间增长趋势是线性的,因此易得时间复杂度是线性阶。 我们将线性阶的时间复杂度记为 ?(?) ,这个数学符号被称为「大 ? 记号 Big‑? Notation」,代表函数 ?(?) 的「渐近上界 asymptotic upper bound」。 我们要推算时间复杂度,本质上是在计算「操作数量函数 ?( 简便地分析出在数据分布 下的整体数学期望。这种情况下,我们一般使用最差时间复杂度来作为算法效率的评判标准。 � 为什么很少看到 Θ 符号? 实际中我们经常使用「大 ? 符号」来表示「平均复杂度」,这样严格意义上来说是不规范的。这 可能是因为 ? 符号实在是太朗朗上口了。如果在本书和其他资料中看到类似 平均时间复杂度 ?(?) 的表述,请你直接理解为 Θ(?) 即可。 2. 复杂度分析 hello‑algo ‧「时间复杂度」统计算法运行时间随着数据量变大时的增长趋势,可以有效评估算法效率,但在某些情况 下可能失效,比如在输入数据量较小或时间复杂度相同时,无法精确对比算法效率的优劣性。 ‧「最差时间复杂度」使用大 ? 符号表示,即函数渐近上界,其反映当 ? 趋于正无穷时,?(?) 处于何种增 长级别。 ‧ 推算时间复杂度分为两步,首先统计计算操作数量,再判断渐近上界。 ‧ 常见时间复杂度从小到大排列有 ?(1)0 码力 | 187 页 | 14.71 MB | 1 年前3
共 22 条
- 1
- 2
- 3