以下是该问题的非常粗略的描述。细节比这复杂得多,但下面的描述说明了我正在寻找的功能。这个小免责声明是为了防止出现“为什么你要用这种方式解决你的问题,而不是我提出的更容易解决的其他方式?”这样的答案 - 我需要以这种方式解决我的问题,原因很多,与这个问题或帖子无关,请不要发布此类回答。
我正在处理分布式网络上的数据集合(大小约为1MB)。这些数据集上执行计算,速度/性能至关重要。我想要一个机制来避免重新传输数据集。也就是说,我需要一种方法为给定大小的每个数据集生成唯一标识符(UID)。 (然后,我将数据集大小和UID从一台机器传输到另一台机器,接收机只需要根据UID判断是否已经在本地拥有它,如果没有,则请求传输数据。)
这类似于使用CRC检查文件的更改,以及使用CRC作为摘要来检测文件之间的重复。我没有看到任何关于后一种用法的讨论。
我不关心篡改问题,即我不需要具有加密强度散列的哈希。
我目前正在使用序列化数据的简单32位CRC,这在目前为止已经为我服务了很好。但是,我想知道是否有人可以推荐哪个32位CRC算法(即哪个多项式?)最适合在这种情况下最小化碰撞的概率?
我另外一个问题有点微妙。在我的当前实现中,我忽略了我的数据集的结构,并有效地仅对表示我的数据的串进行CRC。然而,出于各种原因,我想按以下方式更改我的CRC方法。假设我的顶级数据集是一些原始数据和几个从属数据集的集合。我的当前方案基本上将原始数据和所有从属数据集连接起来,然后CRC结果。然而,大多数时候我已经拥有从属数据集的CRC,我宁愿通过连接原始数据和从属数据集的CRC来构建我的顶级数据集的UID,然后CRC这个构造。问题是,使用这种方法会影响碰撞的概率吗?
为了更好地讨论我的想法,我将定义一些符号。将我的顶层数据集称为
T
,假设它由原始数据集R
和从属数据集S1,S2,...,Sn
组成。我可以写成T = (R, S1, S2, ..., Sn)
。如果&
表示数据集的连接,则我的原始方案可以被看作是:UID_1(T) = CRC(R & S1 & S2 & ... & Sn)
我的新方案可以被认为是:
UID_2(T) = CRC(R & CRC(S1) & CRC(S2) & ... & CRC(Sn))
那么我的问题是:(1)如果
T
和 T'
非常不同,哪个CRC算法能最小化 prob(UID_1(T)= UID_1(T'))
,哪个CRC算法能最小化 prob(UID_2(T)= UID_2(T')),并且这两个概率如何比较?
我关于这个问题的想法很天真和无知。假设 T
和 T'
之间的差异仅在一个从属数据集中,WLOG说 S1!= S1'
。如果发生 CRC(S1)= CRC(S1')
,那么显然我们将有 UID_2(T)= UID_2(T')
。另一方面,如果 CRC(S1)!= CRC(S1')
,那么 R&CRC(S1)&CRC(S2)&...&CRC(Sn)
与 R&CRC(S1')&CRC(S2)&...&CRC(Sn)
之间的差距只有4个字节,因此UID_2检测差异的能力实际上与CRC检测传输错误的能力相同,即它能够检测到仅有几个未被广泛分离的位中的错误。由于这就是CRC的设计目的,所以我认为只要我使用的CRC能够很好地检测传输错误,UID_2就非常安全。用我们的符号表示,
prob( UID_2(T)=UID_2(T') ) = prob(CRC(S1)=CRC(S1')) + (1-prob(CRC(S1)=CRC(S1'))) * probability of CRC not detecting error a few bits.
我们称CRC未检测到少量错误的概率为P
,未检测到大量差异的概率为Q
。以上可以近似表示为:
prob( UID_2(T)=UID_2(T') ) ~ Q + (1-Q)*P
现在我将进一步修改我的UID,具体如下。对于一个“基本”数据,即数据集T=(R)
,其中R只是一个double、integer、char、bool等,定义UID_3(T)=(R)
。然后对于一个由下级数据集T = (S1, S2, ..., Sn)
组成的数据集T
,定义:
UID_3(T) = CRC(ID_3(S1) & ID_3(S2) & ... & ID_3(Sn))
假设一个特定的数据集 T
包含嵌套的子数据集,嵌套深度为 m
级别,那么在某种模糊的意义下,我认为
prob( UID_3(T)=UID_3(T') ) ~ 1 - (1-Q)(1-P)^m
鉴于这些概率在任何情况下都很小,因此可以近似为:
1 - (1-Q)(1-P)^m = Q + (1-Q)*P*m + (1-Q)*P*P*m*(m-1)/2 + ... ~ Q + m*P
如果我知道我的最大嵌套层数“m”,并且我知道各种CRC的“P”和“Q”,那么我想要选择给我最小值的CRC“Q+m*P”。如果像我怀疑的那样,“P~Q”,则以上简化为:UID_1的错误概率是“P”。UID_3的错误概率是“(m+1)P”,其中“m”是最大嵌套(递归)级别。这一切看起来合理吗?
crc32_combine()
,那么您可以预先计算要应用的运算符,然后组合几乎不需要时间。 - Mark Adler