52

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

カウント制限が 未満の項目の小さなリストを反復処理する必要がある場合は、変数の型として の代わりに32000を使用Int16します。を使用する方が本格的な よりも効率的であると想定しているため、これを行います。IntegerInt16Integer

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

4

10 に答える 10

88

インデックスによって配列またはコレクションをループするときは、ほとんどInt32の場合orを使用する必要があります (いや、 orInt64を使用しても信用を得ることはできません)。UInt32UInt64

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

それほど明白でない理由 (および配列がInt32インデックスとして使用される理由) は、CIL 仕様で、すべての操作スタック値がまたはのいずれか であると規定されているためです。値を他の整数型 ( 、、、、または) にロードまたは格納するたびに、暗黙的な変換操作が行われます。符号なしの型には、ロードに対するペナルティはありませんが、値を格納する場合、これは切り捨てとオーバーフロー チェックの可能性があります。署名された型の場合、すべてのロードで符号が拡張され、すべてのストアで符号が折りたたまれます (また、オーバーフロー チェックが行われる可能性があります)。Int32Int64ByteSByteUInt16Int16UInt32UInt64

これが最も害を及ぼすのは、配列へのアクセスではなく、ループ自体です。たとえば、次の無害に見えるループを見てみましょう。

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

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

  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 つの変換があります。また、 orを使用するだけで完全に回避できた可能性があります。Int32Int64

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

于 2008-09-24T20:38:03.307 に答える
54

以下の参考資料によると、ランタイムはInt32のパフォーマンスを最適化し、カウンターやその他の頻繁にアクセスされる操作に推奨します。

本から: MCTS Self-Paced Training Kit (Exam 70-536): Microsoft® .NE​​T Framework 2.0—Application Development Foundation

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

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

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

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

また、同じセクションの表 1-1 には、各タイプの推奨される使用方法がリストされています。この議論に関連するもの:

  • Int16 - 相互運用およびその他の特殊な用途
  • Int32 - 整数とカウンター
  • Int64 - 大きな整数
于 2008-09-25T03:36:40.383 に答える
11

Int16 は、ワード アクセス用の x86 命令が dword アクセス用の命令よりも多くのスペースを占有するため、実際には効率が悪い場合があります。JITが何をするかによって異なります。しかし、反復で変数として使用すると、ほとんどの場合、より効率的ではなくなります。

于 2008-09-24T18:47:54.727 に答える
9

その逆です。

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

Int16 は、データ構造をできるだけスリムにしたい場合に便利です。これにより、スペースが節約され、パフォーマンスが向上する可能性があります。

于 2008-09-24T18:46:54.527 に答える
3

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

リソースが非常に限られている場合、ストレージの観点からは理にかなっている可能性があります。小さなスタックの組み込みシステム、低速ネットワーク用に設計されたワイヤ プロトコル (GPRS など) などです。

于 2008-09-24T18:49:50.837 に答える
2

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

于 2008-09-24T18:51:17.837 に答える
2

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

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

int16 を使用することで修正される実績のあるパフォーマンスの問題に遭遇しない限り、私は int に固執します。

于 2008-09-24T18:47:57.237 に答える
1

ここにある他のものは正しいです。極端なストレージ要件のために必要な場合、またはビジネス オブジェクト フィールドに対する別のレベルの強制のために必要な場合は、Int32 (32 ビット コードの場合)/Int64 (64 ビット コードの場合)未満のみを使用します (もちろん、この場合でも適切なレベルの検証があります)。

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

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

于 2008-09-26T03:37:56.627 に答える
0

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

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

そして、仕様が変更され、カウントしているものはすべて32767 を超える可能性があり、アプリケーションが例外をスローし始めると、面倒なことは絶対に価値がありません...

于 2008-09-24T18:48:02.760 に答える
0

Int32 より小さいデータ型を使用してもパフォーマンスが大幅に向上することはありません。

于 2008-09-24T18:53:46.130 に答える