如何测量表达式的熵/可逆性?LLVM-IR场景技术问询
关于LLVM-IR表达式熵/可逆性的估算方法
首先得明确:你说的“熵”本质是输入为独立真随机变量时,输出的香农熵,它直接反映了函数能传递的信息量上限,和可逆性强相关——可逆函数的输出熵等于输入总位宽(无信息损失),不可逆函数的熵则会因为信息压缩、混淆而降低。
一、精确估算的理论方法
你提到的数据流图最小割是信息瓶颈的上界,而更精确的计算需要结合位级语义分析:
位级依赖与熵分解
把每个输出位的熵单独计算,再结合位之间的相关性计算联合熵。因为输入是独立真随机,每个输入位的熵是1bit:- 对于可逆变换(比如你的
test_a中的zext+shl+or),每个输出位都唯一对应一个输入位,输出位之间相互独立,总熵就是输出位宽(64bit)。 - 对于像
test_c这样的情况,高位是低位的符号扩展,高位和低位完全相关,所以联合熵等于低位的熵(32bit)。
可以基于LLVM的ValueTracking扩展位级依赖分析,追踪每个输出位的输入依赖链,判断是否存在多对一映射或位之间的相关性,进而计算精确熵值。
- 对于可逆变换(比如你的
符号化SMT/SAT分析
用SMT工具(比如Z3)对函数进行符号化分析:- 给输入变量赋予符号化的随机位向量。
- 对输出的每个可能取值,计算对应的输入数量,进而得到输出的概率分布。
- 代入香农熵公式计算精确值。
这种方法能处理复杂的算术运算(比如test_b的乘法),可以准确计算出因为多对一映射导致的熵损失。
数据流图的信息论建模
把LLVM-IR的数据流图转化为信息论中的信道模型,每个操作对应一个信道,计算输入到输出的互信息(当输入是真随机时,互信息等于输出熵)。这种方法可以利用图论中的最小割定理(你提到的上界),再结合操作的语义细化计算,得到更精确的结果。
二、基于随机采样的实用方法
直接输入随机值并分析输出熵是完全可行的,这是工程上快速验证的常用手段,但需要注意几个细节:
- 样本量要足够:对于n位输出,至少需要数十万到数百万量级的样本才能准确估算熵(理论上接近
2^n样本能得到最精确值,但工程中用大样本统计近似即可)。比如64位输出,采样1e6个样本可以得到相对接近真实值的熵估算。 - 熵计算工具:收集输出样本后,用香农熵公式计算:
H = -Σ(p(x) * log2(p(x))),其中p(x)是输出值x出现的频率。 - 局限性:如果函数存在极端稀疏的输出分布,采样可能会低估熵,但对于大多数程序中的计算(比如地址生成、算术运算),这种方法的精度足够满足工程需求。
三、和电路复杂度的关联
你观察到的“低熵计算对应稀疏交叉开关”是完全正确的:
- 低熵意味着输出只依赖于部分输入位,很多输入位的信息没有传递到输出,对应的电路中大量路径是冗余的,交叉开关可以做稀疏化优化。
- 高熵的可逆函数(比如
test_a)需要完整的位映射,每个输入位都影响唯一的输出位,对应的电路复杂度更高,交叉开关也更密集。
举个对应你示例的总结:
test_a:可逆变换,输出每个位都独立对应输入位,熵=64bit。test_b:乘法导致多输入映射到同一输出,输出熵<64bit(无法区分输入顺序或质因数分解)。test_c:只有32位是输入的异或结果,高位与低位完全相关,熵=32bit。
内容的提问来源于stack exchange,提问作者Nonyme




