ทางเลือกที่เร็วกว่าไปยัง CRC คืออะไร


27

ฉันกำลังส่งข้อมูลจาก dsPIC ไปยังพีซีและฉันทำ CRC 8 บิตไปยังบล็อกขนาด 512 ไบต์ทุกบล็อกเพื่อให้แน่ใจว่าไม่มีข้อผิดพลาด เมื่อเปิดใช้งานรหัส CRC ของฉันฉันจะได้รับประมาณ 33KB / s โดยที่ฉันไม่ได้รับ 67KB / s

อะไรคืออัลกอริธึมการตรวจหาข้อผิดพลาดทางเลือกในการตรวจสอบที่จะเร็วขึ้น


5
CRC มีการใช้งานอย่างไร Bitwise? จากนั้นสลับไปใช้วิธีการแบบตาราง bytewise? พิจารณาพื้นที่ความซับซ้อนและการแลกเปลี่ยนเวลาที่เกี่ยวข้องกับการเพิ่มขนาดตารางเป็น 16 บิต (ซึ่งจะทำงานกับสองไบต์พร้อมกัน แต่จะใช้พื้นที่เก็บข้อมูล 64KB)
Aidan Cully

ฉันมี 16KB บน RAM และ ROM 128KB เท่านั้นดังนั้นตาราง 64KB จึงไม่ใช่ตัวเลือก
FigBug

1
ดังนั้นคุณใช้ตาราง 256 ไบต์ใช่ไหม หรือ CRC ระดับบิต หากคุณกำลังทำ bitwise bytewise (ด้วยตาราง 256-byte) จะเร็วขึ้น 8 เท่า
Aidan Cully

ปัจจุบัน Bitwise ฉันจะลองโต๊ะ 256
FigBug

1
67kb / s ถึง 33kb / s? ฉันไม่แน่ใจว่าการประมวลผลอื่น ๆ ของคุณเกี่ยวข้องกับเรื่องใด แต่ดูเหมือนว่าจะมีค่าใช้จ่ายเล็กน้อยแม้แต่สำหรับ PIC อาจมีปัญหาอื่น ๆ ที่ขัดขวางการทำงานของคุณ?
Rei Miyasaka

คำตอบ:


41

ในขณะที่อาจมีตัวเลือกที่เร็วกว่า CRC หากคุณใช้ตัวเลือกเหล่านั้นคุณน่าจะเสียความสามารถในการตรวจจับข้อผิดพลาดไปบ้าง ทางเลือกอื่นอาจใช้รหัส CRC ที่ปรับให้เหมาะกับแอปพลิเคชันของคุณแทน

สำหรับการเปรียบเทียบของซีอาร์ซีมีตัวเลือกอื่น ๆ ให้ดูที่ยอดเยี่ยมคำตอบโดย มาร์ติน ธ อมป์สัน

ทางเลือกหนึ่งที่จะช่วยให้มีนี้เป็นpycrcซึ่งเป็นเครื่องมือ (เขียนในหลาม1 ) ซึ่งสามารถสร้างรหัสที่มา Cสำหรับหลายสิบของการรวมกันของรุ่นซีอาร์ซีและอัลกอริทึม สิ่งนี้ช่วยให้คุณสามารถปรับความเร็วและขนาดให้เหมาะสมที่สุดสำหรับแอปพลิเคชันของคุณเองโดยการเลือกและเปรียบเทียบชุดค่าผสมต่างๆ 1: ต้องการ Python 2.6 หรือใหม่กว่า

สนับสนุนcrc-8 รูปแบบแต่ยังสนับสนุนcrc-5, crc-16และcrc-32หมู่คนอื่น ๆ สำหรับขั้นตอนวิธีการจะสนับสนุนbit-by-bit, และbit-by-bit-fasttable-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เก็บคอมไพล์อยู่บนGitHubเป็นอยู่ของตนติดตามปัญหาแต่ก็ยังสามารถดาวน์โหลดได้จากSourceForge


ฉันไม่เชื่อว่าคนส่วนใหญ่ที่เขียนสิ่งต่าง ๆ สำหรับ PIC กำลังใช้ C แต่อาจใช้งานได้ถ้าเป็นเช่นนั้น
Billy ONeal

4
@Billy - จริงเหรอ? ฉันไม่คิดว่าฉันเจอใครที่พัฒนาสำหรับ PIC ในเชิงพาณิชย์ที่ไม่ได้ใช้ C แน่นอนว่าฉันไม่มีความอดทนสำหรับแอสเซมเบลอร์ในวันนี้และโครงสร้างที่ดี C สามารถจบลงด้วยขนาดที่กะทัดรัด
Mark Booth

ฉันใช้ dsPIC และฉันใช้ C.
FigBug

@FigBug - ขอบคุณดีใจที่คุณชอบคำตอบของฉัน หากคุณใช้การทดสอบเกณฑ์มาตรฐานคุณสามารถแก้ไขคำตอบของฉันด้วยผลลัพธ์ของคุณได้ ฉันชอบที่จะรู้ว่าความแตกต่างของอัลกอริธึมแต่ละอย่างนั้นทำอย่างไรในแง่ของปริมาณงานแอปพลิเคชันของคุณและหน่วยความจำรอยเท้า
Mark Booth

1
โหวตให้ pyCrc อีกครั้งที่นี่ ใช้ในโครงการต่าง ๆ ที่มีข้อ จำกัด แตกต่างกันและมันยอดเยี่ยมมาก
Vicky

11

ความเรียบง่ายแบบหนึ่งบิต (โดยทั่วไปคือ XORing ข้อมูลมากกว่าตัวเองซ้ำแล้วซ้ำอีก) จะเร็วพอ ๆ กับที่จะได้รับ คุณสูญเสียการตรวจสอบข้อผิดพลาดของ CRC เป็นจำนวนมาก

ใน pseudocode:

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

1
ฉันดูเรื่องนี้มาซักพักแล้ว ฉันเชื่อว่าการรวมกันแทน xor ใช้งานได้ดีขึ้นเล็กน้อย (โดยปกติแล้วรวมทุกอย่างแล้วส่งส่วนเติมเต็มของผลรวม 2 เป็น checksum บนเครื่องรับรวมทุกอย่างรวมทั้งที่ได้รับ checksum ผลคือ 0 ถ้าดีทั้งหมดและไม่ใช่ 0 อย่างอื่น)
fast_now

1
@ อย่างรวดเร็ว: ฉันไม่คิดว่ามีความแตกต่างอย่างมีนัยสำคัญระหว่างทั้งสอง - วิธีการทั้งสองไม่ได้ให้การรับรองที่ดีว่าสิ่งต่าง ๆ ไม่ได้รับความเสียหาย หากการเพิ่มเร็วขึ้นสำหรับสถาปัตยกรรมเป้าหมายโดยทั้งหมดให้ใช้วิธีนั้นแทน
Billy ONeal

7
ฉันจำได้ว่า: ความแตกต่างที่สำคัญระหว่าง ADD และ XOR คือการตรวจจับข้อผิดพลาดหลายบิตน้อยกว่า ในกรณีของสตรีมไบต์ข้อผิดพลาดในตำแหน่งบิตเดียวกันจะถูกยกเลิกโดยใช้ XOR เมื่อใช้ ADD การแพร่กระจายของบิตผ่านไบต์ checksum หมายความว่ากรณีนี้สามารถตรวจจับได้มากกว่า (อย่างไรก็ตามข้อผิดพลาดหลายบิตในบิตที่แตกต่างกันแพร่กระจายไปตามกระแสของไบต์มีแนวโน้มที่จะตรวจจับได้น้อยลง - ขึ้นอยู่กับสถานการณ์ในเวลานั้น) การจัดเรียงตรวจสอบใด ๆ เช่นนี้ TERRIBLE สำหรับข้อผิดพลาดแบบหลายบิตดังนั้นจึงเป็นข้อโต้แย้งเล็กน้อย
quick_now

แฮคเกอร์มีประโยชน์น้อยกว่า CRC มาก

3
@ Thorbjørn: ฉันเชื่อว่าฉันยอมรับว่าในคำตอบของฉัน :)
Billy ONeal

10

กระดาษที่ดีจริง ๆ เปรียบเทียบประสิทธิภาพของ checksums และ CRC ต่าง ๆ ในบริบทฝังตัว:

ประสิทธิผลของ Checksums สำหรับเครือข่ายสมองกลฝังตัว

บางคำพูดจากข้อสรุป (ขึ้นอยู่กับการศึกษาความน่าจะเป็นข้อผิดพลาดที่ตรวจไม่พบ):

เมื่อเกิดข้อผิดพลาดในการครอง

XOR, การบวกสองส่วนและการตรวจสอบ CRC ให้ประสิทธิภาพการตรวจจับข้อผิดพลาดที่ดีกว่าการตรวจสอบส่วนประกอบเสริม, Fletcher และ Adler

ในแอพพลิเคชั่นอื่น ๆ

พหุนาม CRC ที่“ ดี” ควรใช้เพื่อจุดประสงค์ในการตรวจจับข้อผิดพลาด

หากค่าใช้จ่ายในการคำนวณมีข้อ จำกัด มาก

(เช่นในกรณีของคุณ) ใช้ (ตามลำดับประสิทธิผล):

คำพูดอื่น ๆ :

เช็คซัมเฟลทเชอร์มีค่าใช้จ่ายในการคำนวณต่ำกว่าเช็คซัมแอดเลอร์และตรงกันข้ามกับความเชื่อที่ได้รับความนิยมก็มีประสิทธิภาพมากขึ้นในสถานการณ์ส่วนใหญ่

และ

โดยทั่วไปแล้วไม่มีเหตุผลใดที่จะดำเนินการตามปกติต่อการใช้เช็คซัมแบบ XOR ในการออกแบบใหม่เนื่องจากมีค่าใช้จ่ายในการคำนวณซอฟต์แวร์เช่นเดียวกับการตรวจสอบเพิ่มเติม แต่มีเพียงครึ่งเดียวที่มีประสิทธิภาพในการตรวจสอบข้อผิดพลาด


1
เป็นโบนัสการตรวจสอบเฟลตเชอร์เป็นเรื่องง่ายมากที่จะใช้
RubberDuck

6

การตรวจสอบ Adlerควรเพียงพอสำหรับการตรวจสอบการบิดเบือนการส่งผ่าน มันถูกใช้โดยไลบรารีการบีบอัด Zlib และถูกนำมาใช้โดย Java 3D Mobile Graphics Standard เพื่อให้การตรวจสอบความสมบูรณ์ของข้อมูลที่รวดเร็ว แต่มีประสิทธิภาพ

จากหน้าวิกิพีเดีย :

การตรวจสอบ Adler-32 นั้นได้มาจากการคำนวณ checksum 16 บิตสองตัว A และ B และเชื่อมบิตของพวกมันให้เป็นจำนวนเต็ม 32 บิต A คือผลรวมของไบต์ทั้งหมดในสตริงบวกหนึ่งและ B คือผลรวมของค่าแต่ละค่าของ A จากแต่ละขั้นตอน

ที่จุดเริ่มต้นของการทำงาน Adler-32 A จะเริ่มต้นได้ที่ 1, B ถึง 0 ผลรวมจะดำเนินการกับโมดูโล 65521 (จำนวนเฉพาะที่ใหญ่ที่สุดมีขนาดเล็กกว่า 2 ^ 16 หรือ 65536) ไบต์จะถูกเก็บไว้ในคำสั่งเครือข่าย (ใหญ่ endian), 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 คือสตริงของไบต์ที่จะคำนวณค่า checksum และ n คือความยาวของ D


โปรดทราบว่า Adler32 นั้นแทบจะไร้ประโยชน์เลยสำหรับข้อมูลระยะสั้น มากถึงประมาณ 180 ไบต์มันสร้างการชนจำนวนมาก
greyfade

+1 - พื้นที่ตรงกลางที่เหมาะสมระหว่าง CRC และความเท่าเทียมกันแบบง่าย
Billy ONeal

@greyfade - FigBug พูดถึงการใช้บล็อก 512 ไบต์ดังนั้นนี่ไม่ควรเป็นปัญหาสำหรับ OP ดีที่จะให้มันสังเกตเห็นสำหรับคนที่มีข้อกำหนดอื่น ๆ แม้ว่า
Mark Booth

5

ฉันไม่ได้ตระหนักถึงสิ่งใดที่มีประสิทธิภาพในการตรวจจับข้อผิดพลาดเหมือนกับ CRC และเร็วกว่า - ถ้ามีคนจะใช้มันแทน

คุณสามารถลองเช็คซัมแบบง่ายๆ แต่มีโอกาสน้อยมากที่จะตรวจพบข้อผิดพลาด


2
ฉันยินดีที่จะละทิ้งประสิทธิภาพสำหรับความเร็ว
FigBug

3

ตรรกะการตรวจสอบตัวเองดีและผู้คนสามารถช่วยด้วยอัลกอริทึมที่เร็วขึ้น

หากคุณต้องการปรับปรุงความเร็วของส่วนประกอบของคุณคุณอาจต้องเปลี่ยนเทคนิคโดยรวมของคุณเพื่อแยกส่วนประกอบการถ่ายโอนออกจากองค์ประกอบการตรวจสอบความถูกต้อง

หากคุณมีสิ่งเหล่านี้เป็นสองรายการอิสระ (ในหัวข้อที่แตกต่างกัน) จากนั้นคุณสามารถรับความเร็วในการถ่ายโอนเต็มและส่งแพ็กเก็ตที่ล้มเหลวอีกครั้งเท่านั้น

อัลกอริทึมจะมีลักษณะดังนี้:

  • เซิร์ฟเวอร์แบ่งออกเป็นขนาดแพ็คเก็ตที่รู้จัก (พูด 1K ชิ้น) วางลงในคิว "ที่จะส่ง"
  • แต่ละแพ็คเก็ตจะถูกส่งไปด้วย ID 16 หรือ 32 บิตและการตรวจสอบของมัน
  • ลูกค้าได้รับแต่ละแพ็คเก็ตและทำให้มันอยู่ในคิวที่จะดำเนินการ
  • บนเธรดที่แยกจากกันไคลเอนต์จะใช้แพ็คเก็ตในแต่ละครั้งทำการตรวจสอบความถูกต้อง
    • ในความสำเร็จมันจะเพิ่มเข้าไปในการรวบรวมแพ็คเก็ตสุดท้าย (ตามลำดับ ID)
    • ในความล้มเหลวจะรายงาน ID ที่ล้มเหลวกลับไปที่เซิร์ฟเวอร์ซึ่งจะจัดคิวแพ็คเก็ตนั้นขึ้นใหม่
  • เมื่อคุณได้รับและตรวจสอบความถูกต้องของแพ็กเก็ตและคุณมี ID ใน sequnce ที่ถูกต้อง (เริ่มต้นที่ 1) คุณสามารถเริ่มเขียนสิ่งเหล่านี้ลงในดิสก์ (หรือทำสิ่งที่จำเป็น)

วิธีนี้จะช่วยให้คุณสามารถรับความเร็วสูงสุดที่เป็นไปได้และถ้าคุณเล่นกับขนาดแพ็คเก็ตของคุณคุณสามารถคำนวณอัตราความล้มเหลวของ optimium VS ตรวจสอบ / ส่งซ้ำอัตรา


2

Checksums เป็นแบบดั้งเดิม

(ลด # '+ สตรีม)

แฮคเกอร์ตามที่ระบุไว้ข้างต้นจะทำงานเช่นกัน

(ลด # 'สตรีม XOR)

แบบแผนที่ซับซ้อนยิ่งขึ้น (ช้ากว่า) เล็กน้อยคือการตรวจสอบพาริตีมาตรฐานสำหรับการเชื่อมต่อแบบอนุกรม

ในระดับนี้คุณกำลังทำการค้าเพื่อความถูกต้องความเร็ว สิ่งเหล่านี้จะล้มเหลวเป็นครั้งคราว

ในระดับที่ซับซ้อนที่สุดถัดไปคุณสามารถใช้สิ่งประเภท crc / hash

การออกแบบอื่นจะเป็นการเพิ่มขนาดของบล็อกที่ใช้สำหรับการสตรีม

คุณควรมีการประมาณอัตราความผิดพลาดจริงเพื่อปรับการเลือกอัลกอริทึมและพารามิเตอร์สำหรับขนาดบล็อก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.