22

現在、32 ビット MIPS プラットフォームを対象としたコード ベース (C、C++ 混合) を使用しています。プロセッサはかなり最新のものです(十分な処理能力とメモリがあることは言うまでもありません)。

コードベースは、uint8[1 バイト幅の符号なし整数]、uint16[2 バイト幅の符号なし整数]、uint32[4 バイト幅の符号なし整数] などのデータ型を使用します。

コードをさまざまなプラットフォームに移植する際に、これらの構造の使用法がどのように役立つかを知っています。

私の質問は次のとおりです。

  1. uint32でも十分な場合にuint16を使用することの使用/利点は何ですか?

  2. より短いデータ型を使用すると、メモリ使用量が節約されますか (データの配置を考慮して)?

  3. 数バイトのメモリを節約する場合、最新のハードウェアで行うのは賢明なことでしょうか?

4

9 に答える 9

23

uint32も十分である場合(もしあれば)、uint16を使用することの使用/利点は何ですか?

それらuint16sが配列または構造の一部である場合は、メモリを節約でき、uint32s同じ配列または構造よりも大きなデータセットを処理できる可能性があります。それは本当にあなたのコードに依存します。

データプロトコルとファイル形式が使用uint16sされる場合があり、代わりに使用するのは正しくない場合がありますuint32s。これは、形式とセマンティクスによって異なります(たとえば、65535から0にラップアラウンドする値が必要な場合uint16は、自動的に実行されますが、実行されuint32ません)。

OTOH、それらuint16sが単一のローカル変数またはグローバル変数である場合、それらを32ビットのものに置き換えても、アライメントのために同じスペースを占める可能性があり、32ビットパラメーターとして(スタックまたはとにかくMIPSで)。

(データアライメントを考慮して)より短いデータ型を使用することで、メモリ使用量を節約できますか?

特にuint16s、大きな配列の多くの構造または要素の一部である場合は、節約できる可能性があります。

数バイトのメモリを節約する場合、最新のハードウェアで行うのは賢明なことですか?

はい、メモリ帯域幅を下げ(これは常に良いことです)、より少ないデータで操作する場合、さまざまなキャッシュミス(データキャッシュとTLB)を下げることがよくあります。

于 2013-02-25T08:22:46.147 に答える
9

まず、uint16 などの型が定義されている場合、それらはどこで定義されているのでしょうか? それらは標準タイプではないため、独自のヘッダーで定義されます-おそらくあなたのものか、サードパーティのライブラリによって提供される可能性があります。その場合、そのコードの移植性と、他のアプリケーションでは意味をなさない可能性のある依存関係を作成しているかどうかを自問する必要があります。

もう1つの問題は、多くのライブラリ(賢明ではないがIMO)がUINT16、uint16、U16 UI16などのさまざまな名前でそのような型を定義しているため、型の一致を保証し、名前の衝突を回避するのがやや悪夢のようになることです。そのような名前定義されている場合は、名前空間に配置するか、ライブラリ固有のプレフィックスを付けて、使用するために定義されたライブラリを示すのが理想的rtos::uint16ですrtos_uint16

ISO C99 標準ライブラリは stdint.h で標準のビット長固有の型を提供するため、独自のヘッダーまたはサードパーティのヘッダーで定義されているものよりも、それらを使用することを優先する必要があります。これらのタイプには_t接尾辞がありuint16_tます。C++ では、std::名前空間に配置できます (ヘッダーが C99 で導入されたため、これは指定されていません)。

1] uint32でも十分な場合にuint16を使用することの使用/利点は何ですか?

stdint.h'sを好むという以前のアドバイスとは別に、uint16_t長さ固有の型を使用する正当な理由が少なくとも 2 つあります。

  1. 特定のハードウェア レジスタ幅に合わせます。
  2. 異なるアーキテクチャ間で共通の互換性のある API を適用するため。

2] 短いデータ型を使用すると、メモリ使用量が節約されますか (データの配置を考慮して)?

おそらくですが、メモリが問題ではない場合、それはそれらを使用する正当な理由ではありません. おそらく大規模なデータ オブジェクトや配列の場合は検討する価値がありますが、グローバルに適用する価値はほとんどありません。

3] 数バイトのメモリを節約する場合、最新のハードウェアで行うのは賢明なことでしょうか?

[2] を参照してください。ただし、 「最新のハードウェア」は必ずしも大きなリソースを意味するわけではありません。たとえば、RAM が数キロバイトしかない 32 ビット ARM Cortex-M デバイスがたくさんあります。これは、設計やアーキテクチャの時代というよりも、ダイ スペース、コスト、消費電力に関するものです。

于 2013-02-25T10:03:36.673 に答える
4

cstdinttypedefには、さまざまな目的のためのがたくさんあります。

  • intN_t特定の幅
  • int_fastN_t少なくとも N ビットを持つ最速の整数の場合
  • int_leastN_t少なくとも N ビットを持つ最小の整数
  • それらのunsigned同等物

状況に応じて選択する必要があります。std::vector大量の計算を行わずに数千を保存しますか? intN_tおそらくあなたの男です。少数の整数で高速な計算が必要ですか? int_fastN_tおそらくあなたの男です。

于 2013-02-25T08:16:30.953 に答える
2

生成されたマシンコード/アセンブラをチェックして、コードが保存されていることを確認する必要があります。RISC 型のアーキテクチャでは、典型的な即値は 16 ビットですが、uint16_t を使用するといずれにしても 32 ビット レジスタがすべて消費されます。したがって、int 型を使用している場合でも、0 に近い値を使用するようにコミットすると、同じ結果が得られ、より移植性が高くなります。

IMO のメモリ節約は、最新のプラットフォームでも価値があります。より厳密なコードは、バッテリー寿命の向上や流暢な UX などにつながります。ただし、(大きな) 配列を操作する場合、または変数が実際の HW リソースにマップされる場合にのみ、サイズを細かく管理することをお勧めします。

ps。コンパイラーは賢いですが、コンパイラーを書いている人々は現在、さらに優れたものにしています。

于 2013-02-25T08:23:45.113 に答える
2

答え。1. ソフトウェアには特定の要件と仕様があり、エンコード/デコードまたはその他の特定の用途で、パラメーターの 8/16 ビットのみを使用するように厳密に指示されています。したがって、u8 say に 127 より大きい値を割り当てても、データは自動的にトリミングされます。

答え。2. 私たちのコンパイラは、メモリや複雑さを問わず、最適化を行うにはインテリジェントをはるかに超えていることを忘れてはなりません。そのため、可能な限り小さいメモリを使用することを常にお勧めします。

答え。3. もちろん、メモリを節約することは、最新のハードウェアでは理にかなっています。

于 2013-02-25T08:03:27.813 に答える
1

uint16_tの代わりに使用すると、uint32_tメモリが節約されます。これはハードウェアの制約の可能性もあります (たとえば、一部の周辺コントローラーは実際には 16 ビットを送信しています!)。ただし、キャッシュとアラインメントの考慮事項があるため、使用する価値がない場合があります (実際にベンチマークする必要があります)。

于 2013-02-25T07:58:36.890 に答える
1

uint32でも十分な場合にuint16を使用することの使用/利点は何ですか?

unsigned charが16 ビット値のCPU があります。このようなコードの単体テストは、typedef を使用しないと困難です (uint16 は、適切な型の単なる typedef です)。

また、これらの typedef を使用すると、さまざまなプラットフォームで簡単にビルドでき、多くの問題は発生しません。

より短いデータ型を使用すると、メモリ使用量が節約されますか (データの配置を考慮して)?

いいえ、それは問題ではありません。uint16が の typedef である場合、どこでもunsigned short使用できますunsigned shortが、異なるプラットフォームでは異なる型を取得する可能性があります。

もちろん、より小さな型を使用すると、メモリ消費量が削減されます。たとえば、配列を使用する場合に限り、uint32 の代わりに uint16 を使用します。

数バイトのメモリを節約する場合、最新のハードウェアで行うのは賢明なことでしょうか?

それはプラットフォームに依存します:

  • メモリ使用量が少ないということは、キャッシュミスが少ないことを意味します
  • サポートされている場合、16 ビット データを処理する SIMD 関数があります。
于 2013-02-25T08:01:34.690 に答える
1

とのような正確な幅の整数型を使用すると、 とint32_tのサイズが異なるプラットフォーム間で符号拡張のバグを回避するのに役立ちます。これらは、たとえば、ビット マスクの適用時やビット シフト時に発生する可能性があります。たとえば、これらの操作を実行し、コードが 32 ビットで機能する場合、64 ビットでは機能しなくなる可能性があります。一方、 を使用すると、プラットフォームに関係なく、どのような結果が得られるかが正確にわかります。intlonglonglonglonguint32_t

また、ビット幅ではなく、格納されたデータのエンディアンのみを考慮する必要があるプラットフォーム間でバイナリ データを交換する場合にも役立ちます。をファイルに書き込むint64_tと、別のプラットフォームでそれを読み取って に格納できることがわかりますint64_t。あるプラットフォームで 64 ビットの代わりにを書き出すと、 32 ビットしかないため、別のプラットフォームではlongが必要になる可能性があります。long longlong

非常に限られた環境 (組み込みのもの) や大規模なデータ セット (5000 万の要素を持つ配列など) について話している場合を除き、通常、メモリの節約は理由ではありません。

于 2013-02-25T08:07:47.413 に答える
1

あなたの質問に対する答えは、1 つの重要な概念に集約されます。それは、データの大きさはどれくらいか? 大量のデータを処理している場合、小さいデータ型を使用する利点は明らかです。次のように考えてみてください。新たに発見された最大の既知の素数を単純に計算すると、一般的なワークステーションでメモリが不足する可能性があります。数値自体は、格納するだけで 1 ギガバイト以上かかります。これには、実際の数を計算するまでの作業は含まれません。シン データ型ではなくシック データ型を使用する場合は、代わりに 2 ギガバイトが表示される可能性があります。単純な例ですが、それでも良い例です。

于 2013-02-25T08:02:38.687 に答える