我正在从dsPIC到PC进行一些数据传输,并且正在对512字节的每个块进行8位CRC校验,以确保没有错误。启用CRC代码后,我的速度约为33KB / s,没有它,则为67KB / s。
有什么替代的错误检测算法可以检查出更快的速度?
我正在从dsPIC到PC进行一些数据传输,并且正在对512字节的每个块进行8位CRC校验,以确保没有错误。启用CRC代码后,我的速度约为33KB / s,没有它,则为67KB / s。
有什么替代的错误检测算法可以检查出更快的速度?
Answers:
尽管可能有比CRC更快的选项,但是如果使用它们,则可能最终会牺牲一定程度的错误检测功能。根据您的错误检测要求,一种替代方法可能是使用针对您的应用程序优化的CRC代码。
有关CRC与其他选项的比较,请参阅Martin Thompson的出色回答 。
pycrc是帮助解决此问题的一个选项,它是一种工具(用python 1编写),可以为crc模型和算法的数十种组合生成C源代码。这样,您可以通过选择不同的组合并进行基准测试来优化自己的应用程序的速度和大小。1:需要Python 2.6或更高版本。
它支持的crc-8
模式,而且还支持crc-5
,crc-16
并且crc-32
在其他之中。至于算法,支持bit-by-bit
,bit-by-bit-fast
和table-driven
。
例如(下载档案):
$ wget --quiet http://sourceforge.net/projects/pycrc/files/pycrc/pycrc-0.8/pycrc-0.8.tar.gz/download
$ tar -xf pycrc-0.8.tar.gz
$ cd pycrc-0.8
$ ./pycrc.py --model=crc-8 --algorithm=bit-by-bit --generate c -o crc8-byb.c
$ ./pycrc.py --model=crc-8 --algorithm=bit-by-bit-fast --generate c -o crc8-bybf.c
$ ./pycrc.py --model=crc-8 --algorithm=table-driven --generate c -o crc8-table.c
$ ./pycrc.py --model=crc-16 --algorithm=table-driven --generate c -o crc16-table.c
$ wc *.c
72 256 1790 crc8-byb.c
54 190 1392 crc8-bybf.c
66 433 2966 crc8-table.c
101 515 4094 crc16-table.c
293 1394 10242 total
您甚至可以做一些时髦的事情,例如使用双半字节查找(带有16字节查找表)进行指定,而不是使用256字节查找表进行单字节查找。
例如(克隆git存储库):
$ git clone http://github.com/tpircher/pycrc.git
$ cd pycrc
$ git branch
* master
$ git describe
v0.8-3-g7a041cd
$ ./pycrc.py --model=crc-8 --algorithm=table-driven --table-idx-width=4 --generate c -o crc8-table4.c
$ wc crc8-table4.c
53 211 1562 crc8-table4.c
考虑到您的内存和速度限制,此选项很可能是速度和代码大小之间的最佳折衷方案。唯一可以确定的方法是对其进行基准测试。
该pycrc Git仓库,在github上,这是它的问题跟踪,但它也可以从下载SourceForge上。
简单的一位奇偶校验(基本上是一遍又一遍地对数据进行异或运算)的速度就差不多。但是,您确实会丢失很多CRC的错误检查。
用伪代码:
char checksum = 0;
for each (char c in buffer)
{
checksum ^= c;
SendToPC(c);
}
SendToPc(checksum);
一篇非常好的论文,比较了嵌入式上下文中各种校验和和CRC的性能:
结论中的一些引述(基于他们对未发现的错误概率的研究):
XOR,二进制补码和CRC校验和提供的错误检测性能比二进制补码,Fletcher和Adler校验和更好。
一个“好的” CRC多项式应尽可能用于错误检测
(根据您的情况),使用(按有效性顺序):
其他语录:
Fletcher校验和比Adler校验和具有更低的计算成本,并且与流行的看法相反,在大多数情况下也更有效。
和
通常没有理由在新设计中继续使用XOR校验和的通用做法,因为它具有与基于加法的校验和相同的软件计算成本,但是在检测错误方面的效率只有大约一半。
的阿德勒校验应足以用于检查传输的失真。它由Zlib压缩库使用,并由Java 3D移动图形标准采用,以提供快速但有效的数据完整性检查。
从维基百科页面:
通过计算两个16位校验和A和B并将它们的位连接为一个32位整数来获得Adler-32校验和。A是字符串中所有字节的总和加1,而B是每个步骤中A的各个值的总和。
在Adler-32运行的开始,A初始化为1,B初始化为0。总和取模65521(最大素数小于2 ^ 16或65536)。字节以网络顺序(大字节序)存储,B占据两个最高有效字节。
该函数可以表示为
A = 1 + D1 + D2 + ... + Dn (mod 65521)
B = (1 + D1) + (1 + D1 + D2) + ... + (1 + D1 + D2 + ... + Dn) (mod 65521)
= n×D1 + (n-1)×D2 + (n-2)×D3 + ... + Dn + n (mod 65521)
Adler-32(D) = B × 65536 + A
其中D是要为其计算校验和的字节字符串,n是D的长度。
校验和逻辑本身很好,人们可以提供更快的算法帮助。
如果要提高组件的速度,则可能需要考虑更改整体技术,以将传输组件与验证组件分开。
如果将它们作为两个独立的项目(在不同的线程上),则可以实现全速传输,并且仅重新发送失败的数据包。
算法看起来像:
这将使您以最快的速度进行传输,如果您使用数据包大小,则可以计算出最佳失败率与验证/重新发送率。
校验和是传统的
(减少#'+流)
上面给出的XOR也可以工作
(减少#'XOR流)
较为复杂(较慢)的方案是串行连接的标准奇偶校验。
在此级别上,您正在为速度而牺牲正确性。这些有时会失败。
在下一个最复杂的级别,您可以使用一些crc / hash类型的东西。
另一种设计是增加用于流的块的大小。
您应该估计实际错误率,以调整算法选择和块大小参数。