3

私は現在、ハンドヘルドポケットやセンサーからデータセンターの大型サーバーまで、幅広いマシンで動作するはずのコードを作成しようとしています。

これらのアーキテクチャ間の(多くの)違いの1つは、整列されたメモリアクセスの要件です。

「標準」のx86CPUでは、整列されたメモリアクセスは必要ありませんが、他の多くのCPUはそれを必要とし、ルールが尊重されない場合は例外を生成します。

これまで、packed属性(またはプラグマ)を使用して、危険であることがわかっている特定のデータアクセスに注意を払うようにコンパイラーに強制することでこれに対処してきました。そしてそれはうまくいきます。

問題は、コンパイラが非常に慎重であるため、プロセスで多くのパフォーマンスが失われることです。

パフォーマンスが重要であるため、厳密に調整されたCPUで特に機能するように、コードの一部を書き直すことをお勧めします。一方、このようなコードは、アラインされていないメモリアクセス(x86など)をサポートするCPUでは低速になるため、厳密にアラインされたメモリアクセスを必要とするCPUでのみ使用します。

そして今、質問:コンパイル時に、ターゲットアーキテクチャが厳密に調整されたメモリアクセスを必要とすることをどのように検出するのですか?(またはその逆)

4

2 に答える 2

5

私が知っている C 実装は、これを理解するのに役立つプリプロセッサ マクロを提供していません。あなたのコードはおそらくさまざまなマシンで実行されるため、テスト用にさまざまなマシンにアクセスできると想定しているため、テスト プログラムで答えを見つけることができます。次に、以下のような独自のマクロを作成できます。

#if defined(__sparc__)
/* Unaligned access will crash your app on a SPARC */
#define ALIGN_ACCESS 1
#elif defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC)
/* Unaligned access is too slow on a PowerPC (maybe?) */
#define ALIGN_ACCESS 1
#elif defined(__i386__) || defined(__x86_64__) || \
      defined(_M_IX86) || defined(_M_X64)
/* x86 / x64 are fairly forgiving */
#define ALIGN_ACCESS 0
#else
#warning "Unsupported architecture"
#define ALIGN_ACCESS 1
#endif

アラインされていないアクセスの速度は、交差する境界に依存することに注意してください。たとえば、アクセスが 4k ページの境界をまたぐ場合は、はるかに遅くなり、さらに遅くなる原因となる他の境界が存在する可能性があります。x86 でも、一部のアライメントされていないアクセスはプロセッサによって処理されず、代わりに OS カーネルによって処理されます。それは信じられないほど遅いです。

また、将来 (または現在) の実装によって、アラインされていないアクセスのパフォーマンス特性が突然変化しないという保証もありません。これ過去に発生しており、将来発生する可能性があります。PowerPC 601 はアラインされていないアクセスに対して非常に寛容でしたが、PowerPC 603e はそうではありませんでした。

状況をさらに複雑にしているのは、アラインされていないアクセスを作成するために作成するコードが、プラットフォーム間で実装が異なるという事実です。たとえば、PowerPC では、 32 ビットの場合、 x << 32andx >> 32は常に 0であるという事実によって単純化されてxいますが、x86 ではそのような運はありません。

于 2012-02-17T23:51:40.537 に答える
5

いずれにせよ、厳密なメモリ アラインメントのためにコードを記述することは良い考えです。アラインされていないアクセスを許可する x86 システムでも、アラインされていない読み取り/書き込みにより 2 つのメモリ アクセスが発生し、一部のパフォーマンスが失われます。すべての CPU アーキテクチャで機能する効率的なコードを書くことは難しくありません。覚えておくべき単純な規則は、ポインターを読み書きするオブジェクトのサイズに合わせる必要があるということです。たとえば、DWORD を書き込む場合は、(dest_pointer & 3 == 0) となります。「UNALIGNED_PTR」型などの松葉杖を使用すると、コンパイラは非効率的なコードを生成します。すぐに動作する必要がある大量のレガシー コードがある場合は、コンパイラを使用して状況を "修正" するのが理にかなっていますが、それが自分のコードである場合は、最初からすべてのシステムで動作するように記述します。

于 2012-02-17T23:28:04.743 に答える