Một thay thế nhanh hơn cho CRC là gì?


27

Tôi đang thực hiện một số truyền dữ liệu từ một DSPIC sang PC và tôi đang thực hiện CRC 8 bit đến mọi khối 512 byte để đảm bảo không có lỗi. Với mã CRC của tôi được kích hoạt, tôi nhận được khoảng 33KB / giây, không có mã này tôi nhận được 67KB / giây.

Một số thuật toán phát hiện lỗi thay thế để kiểm tra sẽ nhanh hơn?


5
CRC được thực hiện như thế nào? Bitwise? Sau đó chuyển sang một phương pháp dựa trên bảng. Tạm biệt? Hãy xem xét không gian, độ phức tạp và sự đánh đổi thời gian liên quan đến việc tăng kích thước bảng lên 16 bit (sẽ hoạt động trên hai byte cùng một lúc, nhưng sẽ mất 64KB lưu trữ bảng).
Aidan Cully

Tôi chỉ có 16KB trên RAM và 128KB ROM, vì vậy bảng 64KB không phải là một tùy chọn.
FigBug

1
Vậy bạn đang sử dụng bảng 256 byte? hoặc CRC bitwise? Nếu bạn đang thực hiện bitwise, bytewise (với bảng 256 byte) sẽ nhanh hơn 8 lần.
Aidan Cully

Bitwise hiện tại, tôi sẽ thử một bảng 256
FigBug

1
67kb / s đến 33kb / s? Tôi không chắc chắn những gì quá trình xử lý khác của bạn liên quan, nhưng điều đó nghe có vẻ khá tốn kém, ngay cả đối với PIC. Có thể có một số vấn đề khác cản trở hiệu suất của bạn?
Rei Miyasaka

Câu trả lời:


41

Mặc dù có thể có các tùy chọn nhanh hơn CRC, nhưng nếu bạn sử dụng chúng thì có khả năng bạn sẽ hy sinh một số mức độ khả năng phát hiện lỗi. Tùy thuộc vào yêu cầu phát hiện lỗi của bạn là gì, một giải pháp thay thế có thể là sử dụng mã CRC được tối ưu hóa cho ứng dụng của bạn.

Để so sánh CRC với các lựa chọn khác, hãy xem câu trả lời xuất sắc của Martin Thompson .

Một tùy chọn để trợ giúp điều này là pycrc là một công cụ (được viết bằng python 1 ) có thể tạo mã nguồn C cho hàng tá kết hợp mô hìnhthuật toán crc . Điều này cho phép bạn tối ưu hóa tốc độ và kích thước cho ứng dụng của riêng bạn bằng cách chọn và điểm chuẩn các kết hợp khác nhau. 1: Yêu cầu Python 2.6 trở lên.

Nó hỗ trợ crc-8 mô hình , nhưng cũng hỗ trợ crc-5, crc-16crc-32trong số những người khác. Đối với các thuật toán , nó hỗ trợ bit-by-bit, bit-by-bit-fasttable-driven.

Ví dụ: (tải xuống kho lưu trữ):

$ 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

Bạn thậm chí có thể thực hiện những điều thú vị như chỉ định bằng cách sử dụng tra cứu nibble kép (với bảng tra cứu 16 byte) thay vì tra cứu byte đơn, với bảng tra cứu 256 byte.

Ví dụ: (nhân bản kho 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

Với các hạn chế về bộ nhớ và tốc độ của bạn, tùy chọn này có thể là sự thỏa hiệp tốt nhất giữa tốc độ và kích thước mã. Cách duy nhất để chắc chắn sẽ là điểm chuẩn mặc dù.


Các pycrc kho git là trên github , như là nó theo dõi vấn đề , nhưng nó cũng có thể được tải về từ SourceForge .


Tôi không tin rằng hầu hết mọi người viết những thứ cho PIC đều sử dụng C, nhưng điều này có thể hoạt động nếu có.
Billy ONeal

4
@Billy - Thật sao? Tôi không nghĩ rằng tôi đã bắt gặp bất kỳ ai đang phát triển cho PIC về mặt thương mại, những người không sử dụng C. Tôi chắc chắn không có sự kiên nhẫn cho trình biên dịch chương trình ngày nay và C có cấu trúc tốt có thể kết thúc khá nhỏ gọn.
Đánh dấu gian hàng

Tôi đang sử dụng một DSPIC và tôi đang sử dụng C.
FigBug

@FigBug - Cảm ơn, rất vui vì bạn thích câu trả lời của tôi. Nếu bạn chạy một số bài kiểm tra điểm chuẩn, vui lòng chỉnh sửa câu trả lời của tôi với kết quả của bạn. Tôi rất muốn biết mỗi thuật toán tạo ra sự khác biệt bao nhiêu về thông lượng ứng dụng và dung lượng bộ nhớ của bạn.
Đánh dấu gian hàng

1
Một phiếu bầu khác cho pyCrc ở đây. sử dụng nó trong các dự án khác nhau với các ràng buộc khác nhau và nó chỉ là tuyệt vời.
Vicky

11

Tính chẵn lẻ một bit đơn giản (về cơ bản XOR dữ liệu lặp đi lặp lại) nhanh như mọi người có thể nhận được. Mặc dù vậy, bạn mất rất nhiều kiểm tra lỗi của CRC.

Trong mã giả:

char checksum = 0;
for each (char c in buffer)
{
    checksum ^= c;
    SendToPC(c);
}
SendToPc(checksum);

1
Tôi đã xem xét điều này một thời gian trước. Tôi tin rằng tổng kết thay vì xor thực sự hoạt động tốt hơn một chút. (thông thường, tính tổng tất cả mọi thứ, sau đó truyền phần bù 2 của tổng dưới dạng tổng kiểm tra. Trên máy thu, tổng tất cả mọi thứ bao gồm cả tổng kiểm tra đã nhận được. Kết quả là 0 nếu tất cả đều tốt và khác 0.)
quick_now

1
@quickly: Tôi không nghĩ rằng có một sự khác biệt đáng kể giữa hai điều đó - không phương pháp nào cung cấp tất cả sự đảm bảo tốt rằng mọi thứ không bị hỏng. Nếu add nhanh hơn trên kiến ​​trúc đích bằng mọi cách hãy sử dụng thay thế.
Billy ONeal

7
Tôi nhớ: Sự khác biệt chính giữa ADD và XOR là có ít khả năng phát hiện lỗi nhiều bit hơn. Trong trường hợp một luồng byte, các lỗi trong cùng một vị trí bit sẽ bị hủy bằng XOR. Khi sử dụng ADD, việc truyền bit lên qua byte tổng kiểm có nghĩa là trường hợp này dễ phát hiện hơn. (Tuy nhiên, nhiều lỗi bit trong các bit khác nhau trải qua luồng byte có khả năng ít bị phát hiện hơn - tùy thuộc vào hoàn cảnh tại thời điểm đó). Bất kỳ sự sắp xếp tổng kiểm tra nào như thế này là TERRIBLE cho các lỗi nhiều bit, do đó, đây là một đối số khá nhỏ.
quick_now

XOR ít hữu ích hơn CRC rất nhiều.

3
@ Thorbjørn: Tôi tin rằng tôi đã thừa nhận điều đó trong câu trả lời của mình. :)
Billy ONeal

10

Một bài báo thực sự tốt so sánh hiệu suất của các tổng kiểm tra và CRC khác nhau trong ngữ cảnh được nhúng:

Hiệu quả của tổng kiểm tra đối với các mạng nhúng

Một số trích dẫn từ các kết luận (dựa trên nghiên cứu của họ về xác suất lỗi không bị phát hiện):

Khi lỗi nổ chiếm ưu thế

XOR, bổ sung bổ sung của hai và tổng kiểm tra CRC cung cấp hiệu suất phát hiện lỗi tốt hơn so với tổng bổ sung của một người, tổng kiểm tra Fletcher và Adler.

Trong các ứng dụng khác

một đa thức CRC tốt, bất cứ khi nào có thể, nên được sử dụng cho mục đích phát hiện lỗi

Nếu chi phí tính toán rất hạn chế

(như trong trường hợp của bạn), sử dụng (theo thứ tự hiệu quả):

Báo giá khác:

Tổng kiểm tra Fletcher có chi phí tính toán thấp hơn tổng kiểm tra Adler và, trái với niềm tin phổ biến, cũng hiệu quả hơn trong hầu hết các tình huống.

Nhìn chung không có lý do để tiếp tục thực hành phổ biến sử dụng tổng kiểm XOR trong các thiết kế mới, bởi vì nó có cùng chi phí tính toán phần mềm như một tổng kiểm tra dựa trên bổ sung nhưng chỉ hiệu quả trong việc phát hiện lỗi.


1
Như một phần thưởng, tổng kiểm tra Fletcher rất dễ thực hiện.
RubberDuck

6

Tổng kiểm tra Adler phải đủ để kiểm tra các biến dạng truyền. Nó được thư viện nén Zlib sử dụng và được Tiêu chuẩn đồ họa di động 3D 3D chấp nhận để cung cấp kiểm tra tính toàn vẹn dữ liệu nhanh chóng nhưng hiệu quả.

Từ trang wikipedia :

Tổng kiểm tra Adler-32 có được bằng cách tính hai tổng kiểm tra 16 bit A và B và ghép các bit của chúng thành một số nguyên 32 bit. A là tổng của tất cả các byte trong chuỗi cộng với một và B là tổng các giá trị riêng lẻ của A từ mỗi bước.

Khi bắt đầu chạy Adler-32, A được khởi tạo thành 1, B thành 0. Các khoản tiền được thực hiện theo modulo 65521 (số nguyên tố lớn nhất nhỏ hơn 2 ^ 16 hoặc 65536). Các byte được lưu trữ theo thứ tự mạng (endian lớn), B chiếm hai byte quan trọng nhất.

Hàm có thể được biểu thị là

 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

Trong đó D là chuỗi byte mà tổng kiểm tra sẽ được tính và n là độ dài của D.


Xin lưu ý rằng Adler32 gần như vô dụng đối với các dữ liệu ngắn. Lên đến khoảng 180 byte, nó tạo ra nhiều va chạm.
greyfade

+1 - một nền tảng trung bình hợp lý giữa CRC và tính chẵn lẻ bit đơn giản.
Billy ONeal

@greyfade - FigBug đã đề cập bằng cách sử dụng các khối 512 byte, vì vậy đây không phải là vấn đề đối với OP. Tốt để có nó lưu ý cho những người có yêu cầu khác mặc dù.
Đánh dấu gian hàng

5

Tôi không biết bất cứ điều gì hiệu quả trong việc phát hiện lỗi như CRC và nhanh hơn - nếu có, mọi người sẽ sử dụng nó thay thế.

Bạn có thể thử kiểm tra đơn giản, nhưng điều đó ít có khả năng phát hiện lỗi.


2
Tôi sẵn sàng từ bỏ một hiệu quả cho tốc độ.
FigBug

3

Vâng, bản thân tổng kiểm tra là tốt và mọi người có thể giúp với các thuật toán nhanh hơn.

Nếu bạn muốn cải thiện tốc độ của thành phần, bạn có thể cần xem xét việc thay đổi kỹ thuật tổng thể của mình để tách biệt thành phần chuyển khỏi thành phần xác nhận.

Nếu bạn có hai mục này là hai mục độc lập (trên các luồng khác nhau) thì bạn có thể nhận được toàn bộ tốc độ chuyển của mình và chỉ gửi lại các gói không thành công.

Thuật toán sẽ trông giống như:

  • Máy chủ chia thành các kích thước gói đã biết (giả sử khối 1K). Đặt chúng trong một hàng đợi "sẽ được gửi".
  • Mỗi gói được gửi qua với ID 16 hoặc 32 bit VÀ tổng kiểm tra của nó.
  • Máy khách nhận từng gói và đặt nó vào hàng đợi để được xử lý.
  • Trên một luồng riêng biệt, máy khách nhận một gói tại một thời điểm, xác thực.
    • Khi thành công, nó thêm nó vào bộ sưu tập gói cuối cùng (theo thứ tự ID)
    • Khi bị lỗi, nó báo cáo ID không thành công trở lại máy chủ, hàng đợi gói đó sẽ được gửi lại.
  • Khi bạn đã nhận và xác thực các gói và bạn có ID theo đúng trình tự (bắt đầu từ 1), bạn có thể bắt đầu ghi chúng vào đĩa (hoặc làm những gì cần thiết).

Điều này sẽ cho phép bạn truy xuất ở tốc độ cao nhất có thể và nếu bạn chơi với kích thước gói của mình, bạn có thể tìm ra tỷ lệ thất bại VS xác thực / tỷ lệ gửi lại.


2

Tổng kiểm là truyền thống

(giảm # '+ luồng)

XOR như đã nêu ở trên cũng sẽ hoạt động tốt

(giảm # 'luồng XOR)

Một lược đồ phức tạp hơn (chậm hơn) là kiểm tra chẵn lẻ tiêu chuẩn cho các kết nối nối tiếp.

Ở cấp độ này, bạn đang giao dịch chính xác cho tốc độ. Những điều này đôi khi sẽ thất bại.

Ở cấp độ tinh vi nhất tiếp theo, bạn có thể sử dụng một số công cụ loại băm / băm.

Một thiết kế khác sẽ là tăng kích thước của khối được sử dụng cho luồng.

Bạn nên có ước tính tỷ lệ lỗi thực tế để điều chỉnh lựa chọn thuật toán và tham số cho kích thước khối.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.