web-dev-qa-db-ja.com

.NET Integer vs Int16?

疑わしいコーディング方法があります。

カウント制限が32000未満のアイテムの小さなリストを反復処理する必要がある場合、Integerではなくi変数タイプにInt16を使用します。 Int16を使用するほうが、本格的なIntegerよりも効率的であると想定しているので、これを行います。

私が間違っている? Int16Integerを使用してもパフォーマンスに効果的な違いはありませんか? Int16の使用をやめ、カウント/反復のすべてのニーズに対してIntegerをそのまま使用する必要がありますか?

50
Matias Nino

以下のリファレンスによると、runtimeInt32のパフォーマンスを最適化し、カウンターやその他の頻繁にアクセスされる操作に推奨します。

本から:MCTS自習型トレーニングキット(試験70-536):Microsoft®.NET Framework 2.0—Application Development Foundation

第1章:「フレームワークの基礎」
レッスン1:「値タイプの使用」

ベストプラクティス:組み込み型によるパフォーマンスの最適化

ランタイムは32ビット整数型(Int32およびUInt32)のパフォーマンスを最適化するため、カウンターおよびその他の頻繁にアクセスされる整数変数にこれらの型を使用します。

浮動小数点演算の場合、演算はハードウェアによって最適化されるため、Doubleが最も効率的な型です。

また、同じセクションの表1-1に、各タイプの推奨される使用法を示します。この議論に関連する:

  • Int16-相互運用およびその他の特殊な用途
  • Int32-整数とカウンター
  • Int64-大きな整数
52
hurst

ほとんど常にInt32またはInt64を使用する必要があります(そして、いいえ、UInt32またはUInt64を使用してクレジットを取得しません)インデックス。

効率が低下する最も明白な理由は、BCLにあるすべての配列とコレクションのインデックスがInt32sを取るため、Int16sを使用しようとするコードで暗黙のキャストが常に発生することですインデックスとして。

それほど明白ではない理由(および配列がInt32をインデックスとして使用する理由)は、CIL仕様で、すべての演算スタック値がどちらかであるInt32またはInt64。他の整数型(ByteSByteUInt16Int16UInt32、またはUInt64)に値をロードまたは保存するたびに、暗黙的な変換操作が含まれます。符号なしの型は、読み込みのペナルティはありませんが、値を格納することにより、切り捨てとオーバーフローチェックの可能性があります。署名されたタイプの場合everyload sign-extends、およびすべてのストアのsign-collapses(およびオーバーフローチェックの可能性があります)。

これがあなたに最も害を与える場所はループ自体であり、配列のアクセスではありません。たとえば、この無邪気に見えるループを見てみましょう。

for (short i = 0; i < 32000; i++) {
    ...
}

よさそうですね?いや!初期化(short i = 0)は1回しか発生しないため、基本的に無視できますが、比較(i<32000)と増分(i++)の部分は32000回発生します。これがマシンレベルでどのように見えるかについてのいくつかのpesudoコードは次のとおりです。

  Int16 i = 0;
LOOP:
  Int32 temp0 = Convert_I16_To_I32(i); // !!!
  if (temp0 >= 32000) goto END;
  ...
  Int32 temp1 = Convert_I16_To_I32(i); // !!!
  Int32 temp2 = temp1 + 1;
  i = Convert_I32_To_I16(temp2); // !!!
  goto LOOP;
END:

32000回実行される3変換がそこにあります。また、Int32またはInt64を使用するだけで完全に回避できた可能性があります。

更新:コメントで述べたように、実際にこのトピックに関するブログ投稿を書いています 。NET Integral Data Types And Yo

84
Alex Lyman

Int16は、Wordアクセス用のx86命令がdwordアクセス用の命令よりも多くのスペースを占めるため、実際にはless効率的です。それはJITが何をするかに依存します。しかし、何があっても、反復で変数として使用する場合は、ほぼ確実にmore効率的ではありません。

11

反対は本当です。

32(または64)整数はint16より高速です。一般に、ネイティブデータ型が最も高速です。

Int16は、データ構造を可能な限り無駄なくしたい場合に最適です。これによりスペースが節約され、パフォーマンスが向上する可能性があります。

9

最新のハードウェアでは、パフォーマンスの違いは非常に小さいため、すべての目的と目的で違いはありません。いくつかのテストハーネスを作成して、両方を数百回実行し、平均ループ完了時間をとると、私の意味がわかります。

リソースが非常に限られている場合、ストレージの観点からは意味があるかもしれません-小さなスタックを備えた組み込みシステム、低速ネットワーク用に設計されたワイヤープロトコル(GPRSなど)など。

3
Russ

効率を決して仮定しないでください。

効率的なものとそうでないものは、コンパイラーごと、プラットフォームごとに異なります。実際にこれをテストしない限り、int16とintのどちらがより効率的かを判断する方法はありません。

Int16修正を使用するという実績のあるパフォーマンスの問題に遭遇しない限り、私は単にintを使い続けます。

2
17 of 26

最高速のパフォーマンスを得るには、32ビットマシンでInt32(または64ビットマシンでInt64)を使用します。 本当にが占めるスペースが気になる場合は、より小さい整数型を使用します(ただし、遅くなる可能性があります)。

2
Mark Cidade

ここでの他のものは正しいです。極端なストレージ要件や別のレベルの強制に必要な場合は、以下 Int32(32ビットコードの場合)/ Int64(64ビットコードの場合)のみを使用してください。ビジネスオブジェクトフィールド(もちろん、この場合でもプロパティレベルの検証が必要です)。

そして一般的には、パフォーマンスの問題が発生するまで、効率について心配する必要はありません。その場合は、プロファイルを作成してください。そして、プロファイリング中に推測して両方の方法で確認しても問題が解決しない場合は、ILコードを確認してください。

良い質問ですが。コンパイラーがどのように機能するかについて、さらに学習します。より効率的にプログラミングする方法を学びたい場合は、ILの基本と、C#/ VBコンパイラーがどのように機能するかを学ぶことは素晴らしいアイデアです。

1
Jon Adams

Int16とintでパフォーマンスが大幅に向上することは想像できません。

変数宣言にいくつかのビットを保存します。

そして、仕様が変更され、カウントしているものがあれば、面倒なことは間違いありませんcanが32767を超えると、アプリケーションが例外をスローし始めたときに気づきます...

0
Dana

Int32よりも小さいデータ型を使用してもパフォーマンスの大幅な向上はありません。実際、メモリ割り当てのために、Int32を使用するとInt16よりも高速になるということをどこかで読みました

0
Leon Tayson