浮点数的存储方式、bf16和fp16的区别

目录

  • 1. 小数的二进制转换
  • 2. 浮点数的二进制转换
  • 3. 浮点数的存储
    • 3.1 以fp32为例
    • 3.2 规约形式与非规约形式
  • 4. 各种类型的浮点数
  • 5. BF16和FP16的区别
  • Ref

1. 小数的二进制转换

十进制小数转换成二进制小数采用「乘2取整,顺序排列」法。具体做法是:用 2 2 2 乘十进制小数,可以得到积,将积的整数部分取出,再用 2 2 2 乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为零,或者达到所要求的精度为止。

然后把取出的整数部分按顺序排列起来,先取的整数作为二进制小数的高位有效位,后取的整数作为低位有效位。

二进制小数转十进制小数则十分简单。我们知道二进制表示整数时,最低位代表 2 2 2 0 0 0 次方,往高位依次是 2 2 2 1 1 1 次方, 2 2 2 次方, 3 3 3 次方。那么对应的,二进制数小数点后面,最高位则是 2 2 2 − 1 -1 1 次方,如下图所示:

因此: ( 0.1101 ) 2 = 1 ⋅ 2 − 1 + 1 ⋅ 2 − 2 + 0 ⋅ 2 − 3 + 1 ⋅ 2 − 4 = ( 0.8125 ) 10 (0.1101)_2=1\cdot2^{-1}+1\cdot2^{-2}+0\cdot2^{-3}+1\cdot2^{-4}=(0.8125)_{10} (0.1101)2=121+122+023+124=(0.8125)10

整数可以使用 2 2 2非负幂次的有限和来表示,但小数就不一定能够用 2 2 2幂次的有限和来表示了,部分情况下可能是无限和。

例如对于小数 0.6 0.6 0.6 而言,它的二进制形式为 0. 1001 ‾ 0.\overline{1001} 0.1001,是一个无限循环小数,循环节是 1001 1001 1001

计算机只能识别 0 0 0 1 1 1,这就是为什么我们需要讨论十进制小数到二进制小数的转换。注意到在上述的例子中, 0.6 0.6 0.6 转换成二进制后是一个无限循环小数,由于计算机内存有限,无法存储无限长的数字序列,因此在实际存储这类数字时,只能存储小数点后的有限位数。这就意味着,无论如何,存储时都必须进行截断或四舍五入处理,而这种操作会引入所谓的「浮点数精度误差」。

很显然,对于这类小数,能够存储的位数越多,相应的精度就越高。这就是为什么 double 类型相比于 float 类型能提供更高精度的原因。

⚠️ 浮点数存储遵循IEEE 754规范。

为加深理解,我们使用Python来实现一遍:

def decimal_to_binary(decimal, max_step=30):binary = '0.'cnt = 0while decimal != 0 and cnt < max_step:decimal *= 2bit = int(decimal)binary += str(bit)decimal -= bitcnt += 1return binaryprint(decimal_to_binary(0.8125))
print(decimal_to_binary(0.6))

2. 浮点数的二进制转换

粗略地讲,一个浮点数由其整数部分小数部分组成,在知道小数的进制转换后,我们可以将一个十进制浮点数转换成二进制形式。

10.625 10.625 10.625 为例。只需注意到

10.625 = 10 + 0.625 = 8 + 2 + 0.5 + 0.125 = 2 3 + 2 1 + 2 − 1 + 2 − 3 \begin{aligned} 10.625&=10+0.625=8+2+0.5+0.125 \\ &=2^3+2^1+2^{-1}+2^{-3} \end{aligned} 10.625=10+0.625=8+2+0.5+0.125=23+21+21+23

于是 ( 10.625 ) 10 = ( 1010.101 ) 2 (10.625)_{10}=(1010.101)_2 (10.625)10=(1010.101)2。我们还可以进一步将其表示成 2 2 2 为底的科学记数法 1010.101 = 1.010101 × 2 3 1010.101=1.010101\times 2^3 1010.101=1.010101×23

一些其他的例子:

3.5 → 1.11 × 2 1 0.8125 → 1.101 × 2 − 1 − 0.6 → − 1. 0011 ‾ × 2 − 1 \begin{aligned} 3.5 &\to 1.11\times 2^1 \\ 0.8125 &\to 1.101\times 2^{-1} \\ -0.6&\to -1.\overline{0011}\times 2^{-1} \\ \end{aligned} 3.50.81250.61.11×211.101×211.0011×21

由此可见,任何(正)十进制浮点数表示成二进制科学记数法以后,一定是 1 1 1 点几(尾数)乘以 2 2 2 的多少次方(指数)。对于负数来说,就是负 1 1 1 点几(尾数)乘以 2 2 2 的多少次方(指数)。因此,任意一个二进制浮点数都可以表示成下面的形式:

V = ( − 1 ) s × M × 2 E (1) V=(-1)^s\times M\times 2^E\tag{1} V=(1)s×M×2E(1)

其中 s s s 代表符号位(sign), s = 1 s=1 s=1 说明是负数, s = 0 s=0 s=0 说明是正数。 M M M尾数(mantissa), E E E指数(exponent)。因此存储一个浮点数只需要存储 s , M , E s,M,E s,M,E 这三部分。


一些发现:

  • 尾数 M M M最高位总是 1 1 1,因此实际存储时,只需要存储尾数的小数部分(fraction),即小数点后面的数字。
  • M ∈ [ 1 , 2 ) M\in[1, 2) M[1,2)。这是因为, M M M 最高位是 1 1 1,所以至少是 1.000... 1.000... 1.000...,极端情况下是 1.111... 1.111... 1.111...,即 1 + 1 2 + 1 4 + . . . 1+\frac12+\frac14+... 1+21+41+...,即使尾数达到了 2 2 2,即 10.000... 10.000... 10.000...,也会被重新规范化到 1.000... 1.000... 1.000...,即 1 1 1
  • E ∈ Z E\in\mathbb{Z} EZ,可正可负可为 0 0 0
  • 注意到 M × 2 − 1 ∈ [ 0.5 , 1 ) , M × 2 1 ∈ [ 2 , 4 ) M\times 2^{-1}\in[0.5,1),\;M\times 2^1\in[2,4) M×21[0.5,1),M×21[2,4)。因此,在十进制下,任何小于 1 1 1 的数转化成二进制后,其指数一定小于 0 0 0;任何大于等于 2 2 2 的数转化成二进制后,其指数一定大于 0 0 0。进一步可知,对于任意非零十进制浮点数 x x x,将其转化成二进制后,其指数为 ⌊ log ⁡ 2 ∣ x ∣ ⌋ \lfloor \log_2|x|\rfloor log2x
  • 只考虑正浮点数(负浮点数亦然)。由上一条知,所有指数将所有的正浮点数 ( 0 , + ∞ ) (0,+\infty) (0,+) 划分成若干个互不相交的区间: ( 0 , + ∞ ) = ⋃ k = − ∞ + ∞ [ 2 k , 2 k + 1 ) (0,+\infty)=\bigcup_{k=-\infty}^{+\infty}[2^k,2^{k+1}) (0,+)=k=+[2k,2k+1)。设有两个符号相同的十进制浮点数 x 1 , x 2 x_1,x_2 x1,x2,它们在二进制下的指数分别为 k 1 , k 2 k_1,k_2 k1,k2,且 k 1 > k 2 k_1>k_2 k1>k2。若 x 1 , x 2 x_1,x_2 x1,x2 均为正,则 x 1 > x 2 x_1>x_2 x1>x2;若 x 1 , x 2 x_1,x_2 x1,x2 均为负,则 x 1 < x 2 x_1<x_2 x1<x2。这说明我们可以仅靠指数来比较两个浮点数的大小(前提是指数不同)。
  • M M M 的位数通常决定了浮点数能表示的精度。例如对于十进制小数 0.6 0.6 0.6 而言,将其转化成二进制后,能存储的尾数位越多,表达自然越精确。 E E E 的位数则决定了浮点数能够表示的数值范围

3. 浮点数的存储

3.1 以fp32为例

IEEE 754规定的浮点数存储格式如下:

最高位是符号位, 1 1 1 代表负数, 0 0 0 代表正数。接下来的若干位是指数位,指数位之后才是尾数位(不存储最高位 1 1 1)。

以fp32(32-bit floating point,32位浮点数)为例,它拥有 1 1 1 位符号位、 8 8 8 位指数位, 23 23 23 位尾数位。

8 8 8 位有符号整数的取值范围是 [ − 128 , 127 ] [-128,127] [128,127],可以表示 256 256 256 个指数。但实际上,我们前面说过,指数不等时可以仅通过指数来比较两个浮点数的大小。为了简化这个比较手续,考虑采用 8 8 8无符号整数进行存储,这样就能仅通过字典序来比较两个指数的大小了。在该设定下,指数的取值范围变成了 [ 0 , 255 ] [0,255] [0,255]

浮点数中还有三个特殊值 0 , ∞ , NaN 0,\infty,\text{NaN} 0,,NaN。IEEE 754规定,需要留一些位置用来表示这些特殊值: 0 0 0 用来留给 0 0 0 255 255 255 用来留给 ∞ , NaN \infty,\text{NaN} ,NaN。挖掉两个位置后,指数的取值范围变成了 [ 1 , 254 ] [1,254] [1,254]。注意到此时还没有负指数,为了平衡正负指数的个数,这里引入指数偏移量 c = 127 c=127 c=127,于是有

存储指数 − 127 = 实际指数 存储指数-127=实际指数 存储指数127=实际指数

故知实际指数的范围为 [ − 126 , 127 ] [-126,127] [126,127]

🧑‍💻 一般地,设 e e e 为指数位的个数,则 c ≜ 2 e − 1 − 1 c\triangleq 2^{e-1}-1 c2e11。fp32的指数偏移量为 2 8 − 1 − 1 = 127 2^{8-1}-1=127 2811=127

例如, 10.625 10.625 10.625 转化成二进制后指数为 3 3 3,那么用来存储的指数值为 127 + 3 = 130 127+3=130 127+3=130,即 10000010 10000010 10000010。尾数部分只需要存储 010101 010101 010101,因此 10.625 10.625 10.625 用fp32表示即为

0 ⏟ 1 个符号位 10000010 ⏟ 8 个指数位 01010100000000000000000 ⏟ 23 个尾数位 \underbrace{0}_{1个符号位}\;\underbrace{10000010}_{8个指数位}\;\underbrace{01010100000000000000000}_{23个尾数位} 1个符号位 08个指数位 1000001023个尾数位 01010100000000000000000

那反过来该如何操作呢?例如,给定一个fp32格式的浮点数 11000001010011000000000000000000,首先分离出它的符号位、指数位和尾数位:

  • 符号位: 1 1 1
  • 指数位: 10000010 10000010 10000010
  • 尾数位: 10011000000000000000000 10011000000000000000000 10011000000000000000000

由符号位可知这是一个负数,将指数位转换成十进制得到 130 130 130,因此实际指数为 130 − 127 = 3 130-127=3 130127=3。由此可知该浮点数的二进制科学记数法表示为 − 1.10011 × 2 3 - 1.10011\times2^3 1.10011×23,从而

− 1.10011 × 2 3 = − 1100.11 = − ( 2 3 + 2 2 + 2 − 1 + 2 − 2 ) = − 12.75 -1.10011\times2^3=-1100.11=-(2^3+2^2+2^{-1}+2^{-2})=-12.75 1.10011×23=1100.11=(23+22+21+22)=12.75

我们还可以用Python来完成这个互相转化的操作:

import structdef binary_to_float(binary_str):assert len(binary_str) == 32, "only support fp32"# 4 bytes, 32 bits.decimal_float = int(binary_str, 2).to_bytes(4, 'big')return struct.unpack('>f', decimal_float)[0]def float_to_binary(value):packed_float = struct.pack('>f', value)binary_str = ''.join(f'{byte:08b}' for byte in packed_float)return binary_strprint(binary_to_float('11000001010011000000000000000000'))
print(float_to_binary(-12.75))

3.2 规约形式与非规约形式

回到 ( 1 ) (1) (1) 式,已知 M ∈ [ 1 , 2 ) M\in[1,2) M[1,2),设有 e e e 个指数位,那么存储指数 E ∈ [ 0 , 2 e − 1 ] E\in[0,2^e-1] E[0,2e1]。当 E ∈ [ 1 , 2 e − 2 ] E\in[1, 2^e-2] E[1,2e2] 时,此时 ( 1 ) (1) (1) 式又称规约形式

还是以fp32为例,只考虑正数,在规约形式下

  • 最小值: M = 1 , E = 1 − 127 = − 126 M=1,\,E=1-127=-126 M=1,E=1127=126,故 V = 2 − 126 ≈ 1.18 × 1 0 − 38 V=2^{-126}\approx1.18\times10^{-38} V=21261.18×1038
  • 最大值: M = 1 + 2 − 1 + ⋯ + 2 − 23 = 2 − 2 − 23 , E = 254 − 127 = 127 M=1+2^{-1}+\cdots+2^{-23}=2-2^{-23},\,E=254-127=127 M=1+21++223=2223,E=254127=127,故 V = ( 2 − 2 − 23 ) ⋅ 2 127 ≈ 3.40 × 1 0 38 V=(2-2^{-23})\cdot2^{127}\approx3.40\times 10^{38} V=(2223)21273.40×1038

很显然,fp32无法表示低于最小值的数,低于最小值的数会被视为 0 0 0(下溢)。同样地,高于最大值的数会被视为 ∞ \infty (上溢)。

更具体地:

  • M = 0 , E = 0 M=0,E=0 M=0,E=0 来表示 0 0 0
  • M = 0 , E = 2 e − 1 M=0,E=2^e-1 M=0,E=2e1 来表示 ∞ \infty
  • M ≠ 0 , E = 2 e − 1 M\neq 0,E=2^e-1 M=0,E=2e1 来表示 NaN \text{NaN} NaN

为了让fp32能表示低于最小值的数(即更接近0的数),并且让从最小规约数向 0 0 0 的过渡更加平滑,非规约数便由此引入。这种设计使得浮点数系统能够更细致地处理接近零的小数值。

我们先思考一下,如何让fp32来表示小于 2 − 126 2^{-126} 2126 的数呢?显然存储指数 E E E 已经达到了最小值 1 1 1,而 M ∈ [ 1 , 2 ) M\in[1,2) M[1,2),将 M M M 的隐含最高位由 1 1 1 改为 0 0 0,从而 M ∈ [ 0 , 1 ) M\in[0,1) M[0,1),我们便可以表示比最小规约数还要小的数。

IEEE 754规定,非规约数的实际存储指数为 0 0 0,而计算公式则为 1 − c 1-c 1c,其中 c c c 为指数偏移量。并且 M ∈ ( 0 , 1 ) M\in(0,1) M(0,1)。当 E = 0 , M ≠ 0 E=0,M\neq0 E=0,M=0 时,则按照非规约数来解析fp32。

我们来计算一下非规约形式下的最小值和最大值:

  • 最小值: M = 2 − 23 , E = 0 M=2^{-23},E=0 M=223,E=0 V = 2 − 23 ⋅ 2 − 126 = 2 − 149 ≈ 1.4 × 1 0 − 45 V=2^{-23}\cdot 2^{-126}=2^{-149}\approx 1.4\times 10^{-45} V=2232126=21491.4×1045
  • 最大值: M = 2 − 1 + 2 − 2 + ⋯ + 2 − 23 = 1 − 2 − 23 , E = 0 M=2^{-1}+2^{-2}+\cdots+2^{-23}=1-2^{-23},E=0 M=21+22++223=1223,E=0 V = ( 1 − 2 − 23 ) ⋅ 2 − 126 ≈ 2 − 126 V=(1-2^{-23})\cdot 2^{-126}\approx2^{-126} V=(1223)21262126

我们还可以进一步计算得到一般形式下的一些结论。设一个浮点数有 e e e 个指数位和 f f f 个尾数位,令 c ≜ 2 e − 1 − 1 c\triangleq 2^{e-1}-1 c2e11,则:

  • 规约形式下的最小值: 2 1 − c 2^{1-c} 21c
  • 规约形式下的最大值: ( 2 − 2 − f ) ⋅ 2 c (2-2^{-f})\cdot 2^{c} (22f)2c
  • 非规约形式下的最小值: 2 1 − c − f 2^{1-c-f} 21cf
  • 非规约形式下的最大值: ( 1 − 2 − f ) ⋅ 2 1 − c (1-2^{-f})\cdot 2^{1-c} (12f)21c

可以看出有以下等式成立:

非规约形式下的最小值 + 非规约形式下的最大值 = 规约形式下的最小值 非规约形式下的最小值+非规约形式下的最大值=规约形式下的最小值 非规约形式下的最小值+非规约形式下的最大值=规约形式下的最小值

关于特殊值的一些结论:

E E E M M M形式
[ 1 , 2 e − 2 ] [1,2^e-2] [1,2e2] [ 1 , 2 ) [1,2) [1,2)规约形式
0 0 0 ( 0 , 1 ) (0,1) (0,1)非规约形式
0 0 0 0 0 0
2 e − 1 2^e-1 2e1 0 0 0无穷
2 e − 1 2^e-1 2e1 ≠ 0 \neq0 =0NaN

4. 各种类型的浮点数

名称指数位尾数位
FP16(半精度浮点数) 5 5 5 10 10 10
BF16(Brain Floating) 8 8 8 7 7 7
FP32(单精度浮点数) 8 8 8 23 23 23
FP64(双精度浮点数) 11 11 11 52 52 52
FP128(四精度浮点数) 15 15 15 112 112 112

5. BF16和FP16的区别

先使用之前得到的公式计算一下规约形式下的最小值和最大值:

类型MinMax
FP16 2 − 14 ≈ 6.10 × 1 0 − 5 2^{-14}\approx 6.10\times10^{-5} 2146.10×105 ( 2 − 2 − 10 ) ⋅ 2 15 = 65504 (2-2^{-10})\cdot 2^{15}=65504 (2210)215=65504
BF16 2 − 126 ≈ 1.18 × 1 0 − 38 2^{-126}\approx1.18\times10^{-38} 21261.18×1038 ( 2 − 2 − 7 ) ⋅ 2 127 ≈ 3.39 × 1 0 38 (2-2^{-7})\cdot2^{127}\approx3.39\times10^{38} (227)21273.39×1038
  • BF16和FP32的指数位相同,像是从FP32中截取了前16位一样。也正是因为指数位相同,使得BF16的数值范围与FP32相似
  • BF16相比FP16的数值范围更大,但是精度会更低(深度学习中,数值范围的重要性是远大于数值精度的)。
  • FP16的数值范围过小,容易造成溢出。
  • FP16更多用于需要较高精度但数值范围要求不是特别严格的场合,如某些图形处理和较轻量级的神经网络模型推理。

Ref

[1] https://blog.csdn.net/u013250861/article/details/131152163
[2] https://www.paddlepaddle.org.cn/documentation/docs/zh/dev_guides/amp_precision/amp_op_dev_guide_cn.html
[3] https://cloud.tencent.com/developer/article/1473541
[4] https://www.runoob.com/w3cnote/decimal-decimals-are-converted-to-binary-fractions.html
[5] https://leokongwq.github.io/2017/08/19/computer-how-float-stored.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/823250.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构复杂度

算法的时间复杂度 常对幂指阶 小练习1 小练习2

【实战】Dubbo应用可观测性升级指南与踩坑记录

应用从dubbo-3.1.*升级到dubbo-*:3.2.*最新稳定版本&#xff0c;提升dubbo应用的可观测性和度量数据准确性。 1. dubbo版本发布说明(可不关注) dubbo版本发布 https://github.com/apache/dubbo/releases 【升级兼容性】3.1 升级到 3.2 2. 应用修改点 注意&#xff1a;Sprin…

qutip,一个高级的 Python 量子力学研究库!

目录 前言 安装 特性 基本功能 量子态的创建和操作 量子态的测量 示例代码 动力学模拟 高级功能 退相干和噪声模拟 控制和优化 量子信息学工具 实际应用场景 量子态演化研究 量子计算机模拟 量子纠错协议 总结 前言 大家好&#xff0c;今天为大家分享一个高级的 Pytho…

机器学习理论入门---线性回归从理论到实践

线性回归是机器学习里面最简单也是最常用的算法&#xff0c;理解了线性回归的推导之后对于后续的学习有很大帮助&#xff0c;所以我决定从这里开始深入学习相关的机器学习模型。 本篇首先从矩阵求导开始切入&#xff0c;然后介绍一次线性回归的推导&#xff0c;再到代码实现。本…

酒店餐厅装水离子雾化壁炉前和装后对比

酒店餐厅装水离子雾化壁炉前和装后的对比可以体现出餐厅氛围和客户体验的显著改变&#xff1a; 装前&#xff1a; 普通的氛围&#xff1a;餐厅可能显得比较普通&#xff0c;缺乏特色或独特的装饰元素。 视觉上缺乏焦点&#xff1a;餐厅空间可能显得相对平淡&#xff0c;缺乏…

压缩感知(ISTA-Net论文)学习笔记

压缩感知&#xff08;ISTA-Net论文&#xff09;学习笔记 第一天&#xff0c;主要查找相关视频和笔记&#xff0c;补全预备知识 【nabla算子】与梯度、散度、旋度_哔哩哔哩_bilibili 近端梯度(Proximal Gradient)下降算法的过程以及理解|ISTA算法|LASSO问题_哔哩哔哩_bilibil…

华为ensp中静态路由和默认路由的原理及配置

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月17日17点37分 默认路由 [Router] ip route-static <目的网络> <目的网络掩码> <下一跳地址>默认路由的作用是将无法匹配路由表中其他路由表项的…

【行业前沿】制造业的数字化转型如何做?

随着科技的迅速发展&#xff0c;数字化转型已经成为制造型企业提高竞争力的关键因素。它可以帮助制造型企业&#xff0c;在产品优化设计、材料采购、生产流程方面实现精细化管理&#xff1b;提升上下游协同生产能力&#xff0c;提高生产效率、降低生产成本、优化产品质量&#…

RUM 最佳实践-视觉稳定性的探索与实践

写在前面的话 在当今数字时代&#xff0c;网页的视觉稳定性对于提供良好的用户体验至关重要。其中一个衡量视觉稳定性的关键指标就是累积布局偏移&#xff08;Cumulative Layout Shift&#xff0c;简称 CLS&#xff09;。CLS 作为 Web Vitals 指标之一&#xff0c;它衡量的是网…

jql联表查询涉及到权限的最好用上临时表

JQL联表查询的两种方法 联表查询 为方便文档描述定义以下两个概念&#xff1a; 临时表&#xff1a;getTemp方法返回的结果&#xff0c;例&#xff1a;const article db.collection(article).getTemp()&#xff0c;此处 article 就是一个临时表虚拟联表&#xff1a;主表与副…

【MySQL数据库】 (篇一 ) 让你快速上手——新手速通版

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、如何起步&#xff1f;&#x1f3c3;‍1.创建数据库&#xff1a;2.选择数据库&#xff1a;3.删除数据库&#xff1a;4.创建表&#xff1a;5.删除表&#xff…

48.基于SpringBoot + Vue实现的前后端分离-雪具销售系统(项目 + 论文PPT)

项目介绍 本站是一个B/S模式系统&#xff0c;采用SpringBoot Vue框架&#xff0c;MYSQL数据库设计开发&#xff0c;充分保证系统的稳定性。系统具有界面清晰、操作简单&#xff0c;功能齐全的特点&#xff0c;使得基于SpringBoot Vue技术的雪具销售系统设计与实现管理工作系统…

Linux的学习之路:12、地址空间(续)与进程的创建、终止和等待

摘要 本章将讲述上章没说的一些东西以及进程创建终止与等待 目录 摘要 一、地址空间&#xff08;续&#xff09; 二、创建 三、终止 四、等待 五、思维导图 一、地址空间&#xff08;续&#xff09; 上篇文章中介绍了地址空间&#xff0c;但是没有说为什么会有地址空间…

通过WSL在阿里云上部署Django项目MySQL

前端用Vue&#xff0c;后端用Django&#xff0c; nginx&#xff0c;Mysql 参照&#xff1a; 通过WSL在阿里云上部署Vue项目_阿里云 wsl-CSDN博客 阿里云重登录 采用Ubuntu系统&#xff0c; apt update #检查是否已经安装 mysql --version systemctl status mysql apt insta…

hook某银行加固app

分析 要在未修复dex并打包情况下对其app内在类进行hook&#xff0c;单纯的hook会由于加固的问题而导致加载不到内在想hook的类。因此需要进行加载加固的classloader。 在此之前需要先了解Context 在Android中&#xff0c;只有Application、Activity以及Service有自己的Contex…

Gradle系列(3)——Gradle extension(gradle扩展),如何自定义gradle扩展,AppPlugin,AppExtension原理

文章目录 1.什么是Extensions2.如何自定义Extension3.问题来了——如何通过自定义Extension给Plugin传递数据4.BaseAppModuleExtension和AppPlugin部分原理BuildTypes是如何创建并传递数据给AppPlugin的&#xff1f;AppPlugin是如何接收数据的&#xff1f;buildTypeContainer流…

HDLbits 刷题 -- Mux256to1

Create a 1-bit wide, 256-to-1 multiplexer. The 256 inputs are all packed into a single 256-bit input vector. sel0 should select in[0], sel1 selects bits in[1], sel2 selects bits in[2], etc. Expected solution length: Around 1 line. 译&#xff1a; 创建一个…

CESS 受邀出席香港Web3.0标准化协会第一次理事会议,共商行业未来

2024 年 4 月 5 日&#xff0c;CESS&#xff08;Cumulus Encrypted Storage System&#xff09;作为香港 Web3.0 标准化协会的副理事会成员&#xff0c;于香港出席了 2024 年度第一次理事会会议。此次会议汇聚了来自不同领域的知名企业和专家&#xff08;参会代表名单见文末&am…

Linux——守护进程

在这篇文章中我介绍了关于tcp网络套接字&#xff0c;关于网络套接字编程的问题我会再次讲述一点东西&#xff0c;然后介绍关于守护进程的知识。 1. 关于网络套接字编程的一些问题 在进行套接字编程时我们一定是得先有套接字&#xff0c;并且我们在使用socket的一些接口时&…

MyBatis 源码分析 - 映射文件解析过程

1.简介 在上一篇文章中&#xff0c;我详细分析了 MyBatis 配置文件的解析过程。由于上一篇文章的篇幅比较大&#xff0c;加之映射文件解析过程也比较复杂的原因。所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来&#xff0c;独立成文&#xff0c;于是就有了本篇文章…