使校验和功能更快

Make checksum function faster

这个校验和计算会被调用很多次:是否可以让下面的校验和函数运行得更快?

我特别想知道是否有可能摆脱 for 循环(因为有人告诉我它们在 python 中很慢)。

sred = b'Standa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008MR191-28'\
       b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
       b'\x00\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc'\
       b'\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xe9\xa8'  

def _check_crc(bstring): 
    crc = 0xffff 
    for b in bstring: 
       crc = crc ^ b 
       for i in range(8): 
          carry_flag = crc & 0x0001 
          crc = crc >> 1 
          if carry_flag == 1: 
              crc = crc ^ 0xa001 
    return crc

_check_crc(sred) # will give 0

这段代码在我的机器上快了大约 10%:

def _check_crc(bstring):
    crc = 0xffff
    for b in bstring:
        crc = crc ^ b
        for i in range(8):
            if crc & 0x0001:
                crc = (crc >> 1) ^ 0xa001
            else:
                crc = crc >> 1
    return crc

这主要是由于取消了对 carry_flag 的分配。布尔比较 if crc & 0x0001: 也可能比比较 1.

快一点

可能还有其他可能的改进,但我现在唯一的进一步想法是尝试在 C 中实现该功能。但是,我不知道这会快多少。按位运算应该已经相当快了。

最快的方法可能是使用 65536 条目查找 table;类似于:

def _check_crc(bstring): 
    crc = 0xFFFF00 
    for b in bstring:
       crc = lookupTable[crc | b]
    return crc >> 8

注意:我将 CRC 和 table 中的所有值“pre-shifted”向左 8 位,以移除循环中间的移位(而不是 table =11=]).

table/list 本身可以是 run-time 生成的,或者是显式的(例如,通过打印出 run-time 生成的列表并将其直接剪切并粘贴到您的源代码中)。我太懒了(并且不记得足够 Python)来显示 run-time 代的示例代码。

我发现这是一个众所周知的算法 (crc16-modbus),并且有 python 模块 (libscrc) 可用于计算校验和。我测试了它,它比我发布的原始代码快得多。