私の32ビットの頭痛は64bit片頭痛?!?(または64bit.純CLRランタイム問題)
質問
何が変わっていますが、予期せぬ結果が発生していパフォーマンスを、メモリ等を切替えた時からの実行.アプリケーションの64ビットJIT対の32ビットJIT?にも興味を持っている良いものについてもっと関心を驚くほど悪く課題の人が走ります。
私の書います。NETアプリケーションを展開するも32bitと64bit.ている多くの疑問に関する問題の移植では、申請私は無関心なの "gotchas"からプログラム/立場からの移植.(ie:取り扱いネイティブ/visual正しく参照型埋め込み構造体のサイズの構造体など)
しかし、 この問いの答え っと思うどんを一望?
ている多くの疑問やブログの投稿るスカート周辺のこの問題は、ヒットの一つですが、したいと思っているもののためにもリストです。
特に私は非常にCPUとともに、大きなメモリ使用量のパターン(そのために必要と64bitの場として、グラフィカルです。私は関係などの隠れた問題が存在する、CLRはJITの走行または64ビットWindows用になります。純3.5sp1).
ここにいくつかの例がありますの課題になっていました意識:
- (今を知っている)物件でも、自動的特性、なinlinedにx64.
- メモリのプロフィール申請の変化、その サイズの参考文献, もので、メモリアロケータは異なる特性
- 起動時に苦しむ可能性があるx64
というのはどのその他の特定課題の人々に発見されJIT64bit Windowsにはものがあれば回避につ。
ありがとうございました。
----編集-----
で明らかに-
それを最適化する試みにおいて早く悪いです。認識していることを推測するシステムが悪いです。また携帯性を64bit独自の課題-および試験64bitシステムの毎日へ。など。
私の応募しなができます。この科学的ソフトウェアアプリケーションへして多くのプロセスすることを100%使用CPUのコアでの高いネジ付きの)時間です。
んのプロファイリングの適用は、大きな違いがある。しかし、プロファイラーを無効に多くの特徴JITので、問題のようなメモリ割り当inliningのJIT等を受ける可能性がありピンときの下で動作プロファイラ.そのため私の必要性の問題をもたらしていました。
解決
よくあるIRCチャンネルから問題を聞いたことを覚えています。 このインスタンスの一時コピーを最適化します:
EventHandler temp = SomeEvent;
if(temp != null)
{
temp(this, EventArgs.Empty);
}
競合状態を戻し、潜在的なnull参照例外を発生させます。
他のヒント
特に面倒な性能の問題です。当期純に関するもの貧しいJIT:
基本的には、inliningおよび構造体などとx64はそのページ ことを示唆 inlining現在の作品がその後のredunantコピーな排除し、その音を疑われる小さな暴.差).
その後、レスリングです。当期純なことに、私の使C++のために何かを数値的に集約的である。でも"良い"場合です。ネんなを扱う構造体を配列の境界をチェックが最適化され、C++のメニューを中心に、定番人気のド当期純 ハ.
いている以上に複雑ド製品の画像が悪くなることがあり非常に早く、きます。純コードの長+未読めに必要なものを手動でインラインのものおよび/または使用できませんのジェネリック医薬品、遅くなります。
私に切り替えを使用 固有 C++:でも、読みやコードおよび高性能薄膜のC++/CLIラッパーを接着剤との間で計算エンジンとゆったりとしています。純ます。
固有の作品のテンプレートのメタプログラミングに統ベクトル表現にSSE固有の指示にしたように、多くのnastiestキャッシュ関連のループ巻き戻しが完了すると、並べ替えまとも注目線形代数学での仕事の整数と非行列の配列表現です。
ですから、インスタンスの場合 P
まるで、このようなものだけで作品:
1.0 / (P.transpose() * P).diagonal().sum();
...しない割り当てを一時的に置き換え変異体のPな計算の全体マトリクス製品の分野かったかもしれません。
そのため、走行できるメンバーとステークホルダー使おうC++C++/CLI ードを動作させることができるかにもかなり良くなったと思います。
ほとんどの場合、Visual Studioとコンパイラーは、問題を隠すのに非常に役立ちます。ただし、プラットフォームを自動検出するようにアプリを設定すると(x86とx64)、32ビットのサードパーティdllに依存する場合に発生する可能性がある1つの大きな問題を認識しています。この場合、64ビットプラットフォームでは、64ビットの規則と構造を使用してdllを呼び出そうとしますが、機能しません。
ポーティングの問題について言及しましたが、それらは懸念事項です。私は(明らかに)あなたのアプリケーションを知りませんが、JITを推測しようとすることはしばしば完全に時間の無駄です。 JITを作成する人々は、x86 / x64チップアーキテクチャを熟知しており、おそらく地球上の誰よりも優れたパフォーマンスと悪いパフォーマンスを知っています。
はい、異なるユニークなコーナーケースが存在する可能性がありますが、「新しいアプリケーションを作成中」の場合は、その後、JITコンパイラについて心配する必要はありません。おそらく、JITを推測することで得られるパフォーマンスの100倍の改善をもたらす愚かなループがどこかで回避される可能性があります。 ORMの作成に遭遇した問題を思い出します。コードを見て、そこから2、3の機械語命令を取り出すことができると思います。もちろん、コードはその後、ネットワーク経由でデータベースサーバーに接続しました。 、そのため、どこかでミリ秒に制限されたプロセスからマイクロ秒を削除していました。
パフォーマンス調整の普遍的なルール...パフォーマンスを測定していない場合、ボトルネックがどこにあるかわからない場合は、あなたが知っている考える。 。そして、あなたはおそらく間違っています。
Quibblesomeの回答について:
Windows 7 x64で次のコードをデバッガなしでリリースモードで実行しようとしましたが、NullReferenceExceptionがスローされたことはありません。
using System;
using System.Threading;
namespace EventsMultithreadingTest
{
public class Program
{
private static Action<object> _delegate = new Action<object>(Program_Event);
public static event Action<object> Event;
public static void Main(string[] args)
{
Thread thread = new Thread(delegate()
{
while (true)
{
Action<object> ev = Event;
if (ev != null)
{
ev.Invoke(null);
}
}
});
thread.Start();
while (true)
{
Event += _delegate;
Event -= _delegate;
}
}
static void Program_Event(object obj)
{
object.Equals(null, null);
}
}
}
64 JITは、このような64ビットアーキテクチャCPUを利用するために完全に開発/移植されていないため、問題があり、問題や予期しない動作を引き起こす可能性のあるアセンブリの「エミュレートされた」動作が発生する可能性があります。これを回避できる場合や、タイムクリティカルな計算とアルゴリズムを作成するための優れた高速64 c ++コンパイラがあるかどうかを調べる場合があります。しかし、情報を見つけるのに苦労したり、逆アセンブルされたコードを読む時間がなかったとしても、マネージコードの外部で大量の計算を行うと、発生する可能性のある問題が少なくなると確信しています。パフォーマンスを向上させます[既にこれを行っていることは確かですが、言及してください:)]
プロファイラーがタイミング結果に大きな影響を与えることはありません。プロファイラーのオーバーヘッドが実際に &quot;重要な場合&quot;おそらく、コードの速度をこれ以上絞ることはできず、ハードウェアのボトルネック(ディスク、RAM、またはCPU)を調べてアップグレードすることを検討する必要があります。 (CPUに縛られているように聞こえるので、そこから始めましょう)
一般に、.netとJITを使用すると、64ビットの移植問題のほとんどから解放されます。ご存知のように、レジスタサイズ(メモリ使用量の変更、ネイティブコードへのマーシャリング、プログラムのすべての部分がネイティブ64ビットビルドである必要がある)およびパフォーマンスの違い(メモリマップの拡大、レジスタの増加、バスの幅に関する影響)がありますなど)、そのため、私はあなたがすでにその面で知っている以上のものを伝えることはできません。私が見た他の問題はC#のものではなくOSです-例えば、64ビットとWOW64アプリケーション用の異なるレジストリハイブがありますので、いくつかのレジストリアクセスは慎重に書かなければなりません。
JITは.net 4または5または6および「最適化」で変更される可能性が高いため、JITがコードで何を行うかを心配し、より適切に動作するように調整しようとすることは一般に悪い考えです。効率が悪くなったり、さらに悪いことにバグになる可能性があります。また、JITは実行中のCPU専用のコードをコンパイルするため、開発PCの改善は別のPCの改善とは限りません。今日のCPUで今日のJITを使用することで何ができるかは、何かをアップグレードするときに1年後には噛み付く可能性があります。
具体的には、「x64でプロパティがインライン化されない」ことを引用します。コードベース全体を実行してすべてのプロパティをフィールドに変換する頃には、インラインプロパティを実行する64ビットの新しいJITが存在する可能性があります。実際、「回避策」よりもパフォーマンスが高い場合があります。コード。 Microsoftに最適化させてください。
メモリプロファイルが変更される可能性があることを正しく指摘します。そのため、より多くのRAM、仮想メモリ用の高速ディスク、およびより大きなCPUキャッシュが必要になる場合があります。すべてのハードウェアの問題。 (たとえば)intではなくInt32を使用することで効果を減らすことができるかもしれませんが、それは大きな違いをもたらさず、潜在的にパフォーマンスを損なう可能性があります(CPUがネイティブの64ビット値をハーフサイズの32ビット値よりも効率的に処理する可能性があるため) )。
「起動時間は長くなる可能性があります」と言いますが、CPU 100%で時間実行すると言うアプリケーションでは、それはむしろ無関係のようです。
それで、あなたは本当に何を心配していますか? 32ビットPCでコードの時間を計ってから、64ビットPCで同じタスクを実行する時間を計るかもしれません。 4時間の実行で30分の差はありますか?または、違いはわずか3秒ですか?それとも64ビットPCは実際に高速ですか?存在しない問題の解決策を探しているのかもしれません。
では、通常の、より一般的なアドバイスに戻ります。ボトルネックを特定するためのプロファイルと時間。適用しているアルゴリズムと数学的プロセスを見て、それらをより効率的なものに改良/置き換えてみてください。パフォーマンスを損なうのではなく、マルチスレッドのアプローチが役立っていることを確認してください(つまり、待機とロックが回避されている)。メモリの割り当て/割り当ての削減を試みます-例オブジェクトを新しいオブジェクトに置き換えるのではなく、再利用します。頻繁な関数呼び出しと仮想関数の使用を減らすようにしてください。 C ++に切り替えて、.netが課すガベージコレクション、境界チェックなどの固有のオーバーヘッドを取り除きます。うーん。 64ビットとは何の関係もありませんか?
64ビットの問題についてはあまり詳しくありませんが、コメントが1つあります:
小さいことは忘れてください 効率は、約97% 時間:早すぎる最適化は すべての悪の根源。 -ドナルドクヌース