0

現在、2 つの 32 ビット マイクロコントローラーでパフォーマンスの比較を行っています。Dhrystone ベンチマークを使用して、両方のマイクロコントローラーで実行しました。1 つのマイクロコントローラーには 4KB の I キャッシュがあり、2 番目のコントローラーには 8KB の I キャッシュがあります。両方のマイクロコントローラーが同じツール チェーンを使用しています。可能な限り、両方のマイクロコントローラーで同じ静的設定と実行時設定を維持しました。しかし、キャッシュが 4KB のマイクロコントローラは、キャッシュが 8KB のマイクロコントローラよりも高速です。両方のマイクロコントローラーは同じベンダーのもので、同じ CPU をベースにしています。

4KBキャッシュを備えたマイクロコントローラーが他のマイクロコントローラーよりも高速である理由を誰かが教えてくれますか?

4

1 に答える 1

0

ベンチマークは一般的に役に立ちません。dhrystone は最も古いものの 1 つであり、パイプラインやコンパイラの最適化が行われる前は、少し価値があったかもしれません。ドライストーンを使い始めたのは15年くらい前だったと思います。

このコードが

.globl ASMDELAY
ASMDELAY:
    sub r0,r0,#1
    bne ASMDELAY
    bx lr

これは主に 2 つの命令であり、最新のプロセッサがどのように機能するかを理解していれば、同じチップ上で実行時間が大きく異なる可能性があります。これを確認するための簡単な方法は、キャッシュやプリフェッチャーなどをオフにして、このコードをオフセット 0x0000 に配置し、何らかの値で呼び出すことです。0x0004 に配置し、次に 0x0008 に配置して繰り返します。これを続けてください。減算と分岐の間に 1 つ、2 つなどの no を配置できます。いろいろなオフセットで試してみてください。

次に、これらのアラインメントごとにキャッシュのオンとオフを切り替えます。フラッシュ用のプロセッサの外部にプリフェッチがある場合は、オンとオフを切り替えます。

次に、特にクロックレートに基づいて待機状態を調整する必要がある MCU の場合は、クロックを変更します。

単一の MCU では、これらの本質的に 2 つの命令の実行時間が非常に大きく異なることがわかります。場合によっては、他の場合よりも 20 倍長くなります。

ここで、小さなプログラムまたはドライス​​トーン プログラムのごく一部を取り上げます。あなたのMCU用にそれをコンパイルすると、いくつの命令が表示されますか? コンパイル コマンド ラインのマイナーからメジャーな最適化とその他のバリエーションを作成します。コードはどの程度変更されますか。2 つの命令が実行時間内に 20 回呼び出されることによって変化する場合、200 命令または 2000 命令でどの程度悪くなるでしょうか? かなり悪くなる可能性があります。

現在使用しているコンパイラ オプションを使用して現在使用している dhrystone プログラムを使用する場合は、ブートストラップに移動し、nop を 1 つ追加して (バイナリ全体をフラッシュで 1 命令分シフトさせます)、再度実行します。2、3、4 を追加します。1 つのシステムでベンチマークを実行するだけで、異なる MCU を比較することはできません。

それぞれがある場合は、dキャッシュの有無にかかわらず、iキャッシュの有無にかかわらず実行します。フラッシュ プリフェッチがある場合はオンとオフを切り替えます。書き込みバッファーがある場合は、オンとオフを切り替えることができます。同じコンパイラ、同じオプション、同じ MCU にまだ残っています。

dhrystone ソース コードのさまざまな関数を取得し、ソース コードで再配置します。Proc_1、Proc_2、Proc_3 の代わりに、Proc_1、Proc_3、Proc_2 にします。上記のすべてをもう一度実行します。もう一度並べ替え、繰り返します。

この MCU を終了する前に、完全に変更されていない同じソース コードの実行時間 (おそらく関数の再配置以外) の実行時間は、大幅に異なる可能性があることを確認する必要があります。

その後、コンパイラ オプションの変更を開始するか、同じソースを保持してコンパイラを変更すると、実行時間にさらに大きな違いが見られます。

今日または昔の dhrystone ベンチマークで、プラットフォームごとに 1 つの結果が得られた可能性はありますか? 簡単に言えば、その結果は幅広い範囲の 1 つにすぎず、実際にはプラットフォームを表していません。

したがって、2 つの異なるハードウェア プラットフォームを比較しようとすると、同じベンダーまたは異なるベンダーの異なる MCU 内の同じアーム コアになります。同じ Verilog コンパイルと合成が使用されたと仮定しても、(これは安全な仮定ではありませんが) 同じコンパイル/ビルド オプションを持つ同じソースであると仮定します。アームが提供するオプションに基づいて、同じコアの変更を行うことができます。いずれにせよ、ベンダーが 2 つのインスタンスで同じベンダーであっても、2 つの異なるベンダーが同じコアをラップしていても、バリエーションが見られます。次に、別のアームやミップなど、まったく異なるコアを使用します。プラットフォームごとに大きく異なるこのようなプログラムを使用して、それらを比較して、どのように価値を得ることができますか?

できません。できることは、ベンチマークを使用して、あるものが別のものよりも優れている、あるコンピューターが別のコンピューターよりも高速である、あるコンパイラーが別のコンピューターよりも高速であるという錯覚を与えることです。コンピュータまたはコンパイラを販売するため。スプリントのカバレッジは Verizons の 1% 以内です...それは何か有益なことを教えてくれますか? いいえ。

式からコンパイラを除外する場合、およびこれらが本当に同じ「CPU」であり、ARM からのソースの同じリビジョンであり、同じ方法で構築されている場合、それらは同じものをフェッチする必要がありますが、キャッシュのサイズはそのため、キャッシュの幅または深さが影響を与える可能性があるため、すでに別の CPU 実装である可能性があります。ソフトウェアでは、16 ビット ポインターではなく 32 ビット ポインターが必要なようなものです (16 ビットではなく 17 ビットですが、ロジックでは一般的に 17 ビットを持つことはできません)。

とにかく、両方のプラットフォームに共通のアドレス空間に対してテスト対象のコードを一度コンパイルする場合は、その空間に同じバイナリを正確に使用し、必要に応じて異なるブートストラップ コードをアタッチできます。C ライブラリが strcpy を呼び出すなどにも注意してください。プラットフォーム間の同じスペースで同じであることで、コンパイラとアライメントが混乱するのを防ぎます。これにより、競技場が平準化される場合とされない場合があります。

これらが同じ CPU であると信じたい場合は、キャッシュをオフにし、上記を実行してコンパイラのバリエーションを排除します。それらが同じように実行されるかどうかを確認してください。プログラムを RAM にコピーして RAM で実行し、フラッシュの問題を解消します。フラッシュで同じ待機状態で両方とも同じクロックを使用していると思いますか?

それらが同じCPUであり、チップベンダーがこれら2つのチップを使用して、メモリシステムがRAMアクセスの場合と同じ数のクロックを使用するようにした場合、そしてそれが実際には同じCPUである場合、最適化を排除することで同じ時間を得ることができるはずです(キャッシング、フラッシュプリフェッチ、アライメント)。

あなたがおそらく見ているのは、コードがコンパイラとキャッシュラインからメモリにどのように配置されているか、またはキャッシュの違い、ヒットとミスの仕組み、および 4KB の違いだけである可能性があるということです。特定の方法でコンパイルされた、特定の方法でメモリに配置された、この特定のプログラムの8KBよりも幸運です。

上記の単純な 2 命令ループを使用すると、同じシステムでパフォーマンスが異なる理由のいくつかを簡単に確認できます。最新の CPU が一度に 8 つの命令をフェッチし、ループがそのフェッチの最後尾に近づきすぎた場合、プリフェッチさらに 8 をフェッチする必要があると考えるかもしれません。確かに、2 つの「フェッチ ライン」にまたがってこれら 2 つの命令を呼び出しているため、キャッシュがあっても、ループごとにより多くのサイクルが必要になります。これらの 2 つの命令がキャッシュ ラインに近づくと (テストごとにアライメントを変更するため)、最終的にこれら 2 つの命令をフェッチするのに 1 回ではなく 2 回のキャッシュ ライン読み取りが必要になると、同じ問題が発生します。少なくとも初回は余分なキャッシュ ラインが読み取られます。

アセンブリ言語の禅、Michael Abrash 氏。この本の github からビルドできる epub/etc があります。この本が出版された時点で 8088 は時代遅れでした。もし 8088 に関する情報がそれだけであるなら、あなたは完全に要点を見失っています。これは、今日の最新のプロセッサ、問題の表示方法、テスト方法、テストのタイミング方法、結果の解釈方法に適用されます。私がこれまで述べてきたすべてのこと、および私が言及していないことについて私が知っているすべてのことは、私が何十年もこれを行ってきたにもかかわらず、本の知識が適用されたことに由来しています.

繰り返しになりますが、コンパイラ、アライメント、CPU、その CPU に関連付けられているメモリ システムなどを完全に排除した場合、キャッシュのサイズのみが変化します。次に、2 つのキャッシュのキャッシュ ラインに対するコードのアラインメントに基づいて、キャッシュ ラインがヒットとミスを異なる方法でフェッチする方法に関連していると考えられます。1 つは、この特定のバイナリに対してヒット数が多く、ミス数が少ない、および/または削除が優れていることです。関数を再配置したり、nops を追加したり、ブートストラップに到達できない場合は、バイナリの下位アドレスに関数全体またはコード (別の printf など) を追加して、リンカーがテスト対象のコードをスライドさせて、プログラムがキャッシュラインとどのように整列するかを変更するさまざまなアドレス。

アラインメントを調整したり、再配置されている関数に基づいてバイナリを大規模に再配置したりすると、2 つのプラットフォームで実行時間の違いが見られるはずです。

結論のベンチマークはあまり多くを教えてくれません。結果は、ポジティブな喜びよりもネガティブな悪臭を放ちます。特定のベンチマークまたはアプリケーションを書き直さなければ、アライメントのために結果を変えようとしても、1 つのプラットフォーム (すべてが同じでキャッシュのサイズが同じであっても、2 つのまったく異なるアーキテクチャであっても) でうまくいく可能性があります。プリフェッチのオフ、書き込みバッファリング、分岐予測など。考えつくすべてのトリックを引き出すと、x から y まで、もう 1 つは n から m まで変化する可能性があり、範囲に重複がある可能性があります。あなたが言うこれらの2つのプラットフォームについて、キャッシュサイズを除いて似ていると思いますが、AがBよりも高速な組み合わせと、BがAよりも高速な組み合わせを少なくとも1つ見つけて、両方で同じ機能をオンまたはオフにしてください。その比較で。他のアプリケーション/ベンチマークに切り替えると、これがすべて最初からやり直されます.dhrystoneの結果がテスト中の他のコードを予測すると仮定する理由はありません. 重要な唯一のプログラム、特に MCU 上のプログラムは、アプリケーションの最終ビルドです。コードの 1 行を変更したり、ブートストラップに 1 つの nop を追加したりするだけでも、1 つの nop の数倍遅くなったり速くなったりする劇的な結果が得られることを覚えておいてください。

于 2016-12-17T11:10:40.440 に答える