CRCのより高速な代替手段は何ですか?


27

私はdsPICからPCへのデータ送信を行っており、エラーがないことを確認するために512バイトのブロックごとに8ビットCRCを行っています。CRCコードを有効にすると、約33KB /秒になりますが、それなしでは67KB /秒になります。

チェックアウトする高速な代替エラー検出アルゴリズムは何ですか?


5
CRC自体はどのように実装されていますか?ビット単位?次に、テーブルベースの方法に切り替えます。バイト単位?テーブルサイズをたとえば16ビットに増やすことに伴うスペース、複雑さ、時間のトレードオフを考慮してください(一度に2バイトで動作しますが、64KBのテーブルストレージが必要になります)。
エイダンカリー

RAMに16KBとROMの128KBしかありませんので、64KBのテーブルはオプションではありません。
FigBug

1
256バイトのテーブルを使用していますか?またはビットごとのCRC?ビット単位で行う場合、バイト単位(256バイトのテーブルを使用)は8倍高速になります。
エイダンカリー

現在、ビット単位で、256テーブルを試してみます
-FigBug

1
67kb / s〜33kb / s?他の処理が何を伴うのかはわかりませんが、PICであってもかなりのオーバーヘッドのように聞こえます。パフォーマンスを妨げる他の問題があるかもしれませんか?
宮坂

回答:


41

CRCよりも高速なオプションがありますが、それらを使用すると、ある程度のエラー検出機能が犠牲になる可能性があります。エラー検出要件に応じて、代わりにアプリケーションに最適化されたCRCコードを使用することもできます。

CRCと他のオプションとの比較については、Martin Thompsonによる優れた回答を 参照してください。

これを支援するオプションの1つは、pycrcです。これは、crcモデルアルゴリズム多数の組み合わせに対してCソースコードを生成できるツール(python 1で記述)です。これにより、さまざまな組み合わせを選択してベンチマークすることにより、アプリケーションの速度とサイズを最適化できます。1:Python 2.6以降が必要です。

それはサポートしていcrc-8 たモデルを、だけでなく、サポートcrc-5crc-16およびcrc-32他の中。用としてのアルゴリズム、それがサポートしbit-by-bitbit-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

256バイトのルックアップテーブルでのシングルバイトルックアップではなく、デュアルニブルルックアップ(16バイトのルックアップテーブル)を使用して指定するなど、ファンキーなこともできます。

例(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の


PIC向けのものを書いているほとんどの人がCを使用しているとは思わないが、もしそうならうまくいくかもしれない。
ビリーONeal

4
@ビリー-本当に?C 使用していないPIC向けに商業的に開発している人に出会ったことはないと思います。最近のアセンブラーに忍耐力はなく、よく構成されたCはかなりコンパクトになります。
マークブース

dsPICを使用しており、Cを使用しています。
FigBug

@FigBug-ありがとう、私の答えが気に入ってくれてありがとう。ベンチマークテストを実行する場合は、結果を使用して回答を自由に編集してください。アプリケーションのスループットとメモリフットプリントに関して、各アルゴリズムがどの程度の違いをもたらすかを知りたいと思います。
マークブース

1
pyCrcへの別の投票はこちら。さまざまな制約のあるさまざまなプロジェクトで使用することは素晴らしいことです。
ヴィッキー

11

単純な1ビットパリティ(基本的に、データ自体を何度もXOR演算する)は、取得できる速度とほぼ同じです。ただし、CRCのエラーチェックの多くは失われます。

擬似コードで:

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

1
少し前にこれを調べました。実際、xorの代わりに合計する方が少しうまくいく思います。(通常、和のすべてが、その後、チェックサムなどの和の2の補数を送信し、受信機で、和のすべてがその受信したチェックサムを含む結果があれば、そのすべての良い、非0そうでなければ0である。。。)
quickly_now

1
@quickly:これらの2つの間に大きな違いはないと思います-どちらの方法も、物事が破損していないという十分な保証を提供しません。ターゲットアーキテクチャ上で追加がより高速である場合は、必ずそれを使用してください。
ビリーONeal

7
記憶しました:ADDとXORの主な違いは、複数ビットエラーの検出可能性が低いことです。バイトストリームの場合、同じビット位置のエラーはXORを使用してキャンセルされます。ADDを使用する場合、チェックサムバイトまでのビットの伝播は、このケースがより検出しやすいことを意味します。(ただし、バイトストリーム全体に広がるさまざまなビットの複数のビットエラーは、その時点の状況によっては検出されにくい可能性があります)。このようなチェックサムの配置は、マルチビットエラーの場合はひどいので、かなりマイナーな議論です。
すぐに

XORはCRCよりもはるかに役に立ちません。

3
@Thorbjørn:私は自分の答えでそれを認めたと思う。:)
ビリー・オニール

10

組み込みコンテキストでのさまざまなチェックサムとCRCのパフォーマンスを比較する非常に優れた論文:

組み込みネットワークのチェックサムの有効性

結論からのいくつかの引用(検出されないエラー確率の研究に基づく):

バーストエラーが支配的な場合

XOR、2の補数加算、およびCRCチェックサムは、1の補数加算、フレッチャー、およびアドラーチェックサムよりも優れたエラー検出パフォーマンスを提供します。

他の用途

エラー検出には、可能な限り「適切な」CRC多項式を使用する必要があります

計算コストが非常に制約されている場合

(あなたの場合のように)、使用する(効果の順に):

その他の引用:

フレッチャーチェックサムは、Adlerチェックサムよりも計算コストが低く、一般的な考えに反して、ほとんどの状況でより効果的です。

そして

一般に、新しいデザインでXORチェックサムを使用する一般的な方法を継続する理由はありません。XORチェックサムは、追加ベースのチェックサムと同じソフトウェア計算コストを持っていますが、エラーの検出で約半分の効果しかないためです。


1
おまけとして、フレッチャーチェックサムの実装は非常に簡単です。
ラバーダック

6

アドラーチェックサムは、伝送歪みをチェックするための十分なはずです。Zlib圧縮ライブラリで使用され、Java 3Dモバイルグラフィックス標準で採用され、高速でありながら効果的なデータ整合性チェックを提供します。

ウィキペディアのページから:

Adler-32チェックサムは、2つの16ビットチェックサムAおよびBを計算し、それらのビットを連結して32ビット整数にすることにより取得されます。Aは文字列のすべてのバイトに1を加えた合計で、Bは各ステップからのAの個々の値の合計です。

Adler-32実行の開始時に、Aは1に初期化され、Bは0に初期化されます。合計は65521を法として行われます(2 ^ 16または65536より小さい最大素数)。バイトはネットワーク順(ビッグエンディアン)に格納され、Bは最上位2バイトを占有します。

関数は次のように表現できます

 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の長さです。


Adler32は、短いデータの実行にはほとんど役に立たないことに注意してください。最大約180バイトで、多数の衝突が発生します。
-greyfade

+1-CRCと単純なビットパリティの合理的な中間点。
ビリーONeal

@greyfade-FigBugは512バイトブロックを使用することに言及しているので、これはOPにとって問題になりません。ただし、他の要件がある人には注意してもらうとよいでしょう。
マークブース

5

CRCほどエラー検出に効果的で高速なものはありません。もしあれば、人々は代わりにそれを使用するでしょう。

簡単なチェックサムを試すこともできますが、エラーを検出する可能性ははるかに低くなります。


2
スピードの有効性をあきらめます。
FigBug

3

さて、チェックサムロジック自体は優れており、人々はより高速なアルゴリズムを支援できます。

コンポーネントの速度を改善したい場合は、検証コンポーネントから転送コンポーネントを分離するために全体的なテクニックを変更する必要があるかもしれません。

これらを2つの独立したアイテムとして(異なるスレッドで)持っている場合は、転送速度を最大にして、失敗したパケットのみを再送信できます。

アルゴリズムは次のようになります。

  • サーバーは、既知のパケットサイズ(1Kチャンクなど)に分割されます。それらを「送信予定」のキューに入れます。
  • 各パケットは、16ビットまたは32ビットのIDとそのチェックサムとともに送信されます。
  • クライアントは各パケットを受信し、キューに入れて処理します。
  • 別のスレッドでは、クライアントは一度にパケットを受け取り、検証を行います。
    • 成功すると、パケットの最終コレクション(ID順)に追加されます。
    • 失敗すると、失敗したIDをサーバーに報告し、サーバーはそのパケットを再送信するためにキューに入れます。
  • パケットを受信して​​検証し、正しいシーケンス(1から開始)のIDを取得したら、ディスクへの書き込みを開始(または必要なことを実行)できます。

これにより、可能な限り最高の速度で送信できるようになり、パケットサイズを試してみると、最適な失敗率と検証/再送率を計算できます。


2

チェックサムは伝統的です

(# '+ストリームを減らす)

上記のXORも同様に機能します

(# 'XORストリームを削減)

少し複雑な(遅い)スキームは、シリアル接続の標準パリティチェックです。

このレベルでは、速度と正確さを犠牲にしています。これらは時々失敗します。

次の最も高度なレベルでは、crc / hashタイプのものを使用できます。

別の設計は、ストリームに使用されるブロックのサイズを増やすことです。

アルゴリズムの選択とブロックサイズのパラメーターを調整するには、実際のエラー率を推定する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.