web-dev-qa-db-ja.com

uint8、uint16などの使用

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

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

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

私の質問は:

  1. Uint32でも十分である(もしあれば)uint16を使用する際の使用/利点は何ですか?

  2. 短いデータ型を使用すると、メモリ使用量が節約されますか(データのアライメントを考慮)。

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

19
NeonGlow

Uint32でも十分である(もしあれば)uint16を使用する際の使用/利点は何ですか?

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

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

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

短いデータ型を使用すると、メモリ使用量が節約されますか(データのアライメントを考慮)。

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

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

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

23
Alexey Frunze

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

別の問題は、多くのライブラリ(不適切なIMO)がUINT16、uint16、U16 UI16などのさまざまな名前でそのような型を定義することで、型の一致を保証し、名前の衝突を回避するのはやや悪夢になります。このような名前areが定義されている場合、理想的には名前空間に配置するか、使用するために定義されたライブラリを示すライブラリ固有のプレフィックスを指定する必要があります(例:_rtos::uint16_ to _rtos_uint16_。

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

1] uint32でも十分な場合にuint16を使用する場合の使用/利点は何ですか(ある場合)。

_stdint.h_の_uint16_t_を優先するという以前のアドバイスとは別に、長さ固有の型を使用する正当な理由が少なくとも2つあります。

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

2]短いデータ型を使用すると、メモリ使用量が節約されますか(データのアライメントを考慮)。

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

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

[2]を参照してください。 "現代のハードウェア"は、必ずしも大きなリソースを意味するわけではありません。多くの32ビットARM少数のCortex-MデバイスKb of RAM。たとえば、設計やアーキテクチャの時代よりも、ダイのスペース、コスト、消費電力の方が重要です。

9
Clifford

cstdint には、さまざまな目的でtypedefsの負荷があります。

  • intN_t特定の幅
  • int_fastN_t少なくともNビットの最速の整数
  • int_leastN_t少なくともNビットの最小整数
  • unsignedに相当するもの

状況に応じて選択する必要があります。 std::vectorと計算の負荷をしていない? intN_tはおそらくあなたの男です。少数の整数で高速計算が必要ですか? int_fastN_tはおそらくあなたの男です。

4

生成されたマシンコード/アセンブラをチェックして、コードが保存されていることを確認する必要があります。 RISCタイプのアーキテクチャでは、一般的なイミディエートは16ビットですが、uint16_tを使用すると、とにかく完全な32ビットレジスタが消費されます。したがって、int型を使用する場合、ゼロに近い値を使用すると、同じ結果が得られ、移植性が向上します。

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

追伸コンパイラーは賢いですが、それらを書いている人々は、現時点ではそれらをさらに良くします。

2
Aki Suihkonen

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

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

回答3.もちろん、メモリの節約は現代のハードウェアでは理にかなっています。

2
paper.plane

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

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

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

1
Nikos C.

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

Uint32でも十分である(もしあれば)uint16を使用する際の使用/利点は何ですか?

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

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

短いデータ型を使用すると、メモリ使用量が節約されますか(データのアライメントを考慮)。

いいえ、それはポイントではありません。 uint16unsigned shortのtypedefである場合、どこでもunsigned shortを使用できますが、プラットフォームごとに異なる型を取得できます。

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

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

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

  • メモリ使用量が少ないということは、キャッシュミスが少ないことを意味します
  • サポートされている場合、16ビットデータを処理するSIMD関数があります
1
BЈовић

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

1
L0j1k