7

ちょうど 2 つのスレッドを持つ Windows フォーム アプリケーションがあります。これらのスレッドは相互にゼロの相互作用を持っています.Ala最初のスレッドは2番目のスレッドを台無しにすることなく実行されます. それが起こる必要がないので、それらの間の同期はありません。最初のスレッドは、アプリケーションの UI を処理し、色とラベルを変更し、1 つのタイマーを実行してユーザー入力をキャッチします。このタイマーは 200 ミリ秒ごとに起動します。2 番目のスレッドはより複雑で、ユーザーがアプリケーションを終了してシャットダウンするまで、コーディングを継続的に実行します。

2 番目のスレッドは、最初にメモリからデータを読み取り、リストに格納してから、このデータを使用して計算を行います。2 番目のスレッドの 1 回の反復を完了するのにかかる時間を測定するための StopWatch クラス タイマーがあります。このタイマーはリセットされ、スレッドの最初で開始され、スレッドが反復を完了すると停止してコンソールに出力されます。これは、パフォーマンス データを取得している場所です。私は、スレッドを少なくとも 1000 回繰り返し実行させ、最初の実行を除いて平均を計算しました。

ビルドの DEBUG バージョン。つまり、VSHOST によって実行されるビルド、または Visual Studio C# 2010 Express で F5 キーを押したときに実行されるビルドです。タイミングの平均は 0.00035 秒、つまり 0.35 ミリ秒です。

Ctrl-F5 キーを押すか、BUILD を押したときに生成される .exe からアプリケーションを実行することによって、アプリケーションが VSHOST の外部で実行される場合。また、REBUILD を使用して、まったく変更を加えずにこれをテストしました。タイミングの平均は 0.365 秒、つまり 365 ミリ秒です。これは、Release Build では約 1000 倍遅くなります。

私は何が起こっているのか完全に途方に暮れています。プログラムを非常に迅速に実行できるようにするVSHOSTの機能は何ですか。すべての変数の初期化が考慮され、正しいことを確認しました。そうは言っても、なぜこのようなことが起こるのか、私にはわかりません。なぜ私がそのようなパフォーマンスの落ち込みを得ているのかについての洞察はありますか?

余談ですが、私が使用しているコンピューターは 64 ビットで、ハイパー スレッディングを備えたクアッド コア i7、16 ギガバイトの RAM、ツイン HD6750 を搭載しています。したがって、スレッドが多すぎるという問題ではないようです。ここで問題になる可能性があるのは、ハイパースレッディングだけです。

私のアプリケーションが何をするかという形でのコードのスニペット。ただし、メモリアドレスの読み取りがスローダウンが発生する場所であるため、動作するコードを提供することはできません。

namespace Test Snippet
{
public struct Data
{
    public float X;
    public float Y;
    public float Z;
    public float dX;
    public float dY;

    public Data(int c)
    {
        this.X = ReadFloat(Base + 0x50 + (c * 0x10));
        this.Y = ReadFloat(Base + 0x50 + (c * 0x10));
        this.Z = ReadFloat(Base + 0x50 + (c * 0x10));
        if (this.Z == 1)
        {
            targetindex = c;
        }
        this.dX = 0;
        this.dY = 0;
    }
}
class Class1
{
    public int Base = new int();
    public List<Data> data = new List<Data>();
    public int targetindex = new int();
    public Data targetdata = new Data();

    public void GetData()
    {
        while (true)
        {
            data.Clear();
            for (int c = 0; c < 64; c++)
            {
                Data tempdata = new Data();
                teampdata = new Data(c);
                data.Add(tempdata);
            }
            if (data.Count != 0)
            {
                targetdata = data[targetindex];
                data.RemoveAt(targetindex);
                targetdata.dX = ReadFloat(Base + 0x66);
                targetdata.dY = ReadFloat(Base + 0x65);
                Data[] tempdatarray = new Data[data.Count];
                for (int j = 0; j < tempdatarray.Length; j++)
                {
                    tempdatarray[j].dX = (float)Math.Acos(targetdata.dX * 10);
                    tempdatarray[j].dY = (float)Math.Acos(targetdata.dY * 10);
                }
            }

        }
    }
}

}

編集::同じ手順を試しましたが、スレッドを使用しませんでした。ユーザー入力をキャッチするために使用していたタイマーによって呼び出されるスレッド関数がありました。私は同じ結果を得ています。つまり、スレッド化は問題ではないようです。別のコンピューターでもテストを行いましたが、何らかの理由で大きな違いが得られません。これにより、コンピューターに問題があるか、ハイパースレッディング機能によりプロセッサがスレッドを処理する方法に問題がある可能性があると思います。プログラム内からハイパー スレッディングを明示的に利用していないマルチスレッド アプリケーションで、ハイパー スレッディングが問題を引き起こすかどうかは誰でも知っています。正直なところ、セットアップ方法がわかりません。

4

3 に答える 3

1

リリース ビルドを選択しているとは言えません。これはツールバーのオプションです。デバッグ ビルドを直接実行している場合は、見つからないものを探している可能性があります。

編集:見逃したタイトルを除いて!!!! :-)

于 2012-09-06T22:28:29.557 に答える
1

そのため、最初にパフォーマンス プロファイリングを行う必要があります。プロファイリングツールを使用するか、タイマーを使用して、特定の処理にかかる時間を示すメッセージをどこかに出力します。これにより、実行中の理由がわからない場合でも、少なくともコードのどの行がゆっくりと実行されているかを突き止めることができます。デバッガーの下では非常に遅くなります。この情報がなければ、当て推量しかありません。

さて、推理へ…

これらの観察に基づいて、問題はコンソールの使用に関係していると思います

  • コンソール ウィンドウ自体への書き込みは、実際には比較的低速です。これは、コンソールに多くの内容を書き込むアプリケーションを実行している場合に見られます。ウィンドウを開いたままにしておくと、実行に時間がかかりますが、コンソール ウィンドウを最小化すると、同じ操作をより速く実行できます。
  • 私が理解しているように、0.35ms ごとにコンソールに 1 つのメッセージを書き込んでいます。それはたくさんのメッセージです。
  • アプリケーションの実行方法に応じて、Visual Studio はデバッグ時にコンソール出力を Visual Studo 内の「出力」ウィンドウに実際にリダイレクトします。

私の推測では、Visual Studio のコンソール ウィンドウは、デバッグしていないときに使用される同等のメカニズムよりもはるかに高速であり、さらに遅くなる原因は実際にはログ コードにあると考えられます。コンソールベースのログを取り出して、代わりにファイルにログを記録してみて、違いがあるかどうかを確認するか、メッセージをログに記録する回数を減らしてください。たとえば、100 回の反復を完了するのにかかる時間をログに記録します。これにより、影響が軽減されます (コンソールがあなたのパフォーマンスに持っていること。

于 2012-09-07T14:07:05.967 に答える
0

この問題は、ハイパースレッディングとは何の関係もありません。リンクが見つかりませんが、2004年のIntelからの、それがどのように機能するかについての優れた技術的説明があります(マーケティングの誇大宣伝はありません)。ただし、不足しているのは、コア0はおそらく実際のコアであり、コア1はおそらくコア0と同じハードウェアを共有する論理コアです。私たちの観点(アプリ開発者)では、コア0と1の両方が実際であり、そうではありません。コア1が論理コアであるという事実に注意する必要があります(明らかなことを除いて、論理コアは全体で約13〜30%のパフォーマンスブーストしか提供しません。これも技術的な説明で説明されています)。Windowsは、実際のコアと論理コアにわたってスレッドをスケジュールするのに非常に優れています。あなたがしなければならないのは2つのスレッドを作成することだけで、Windowsはコア0と1でそれぞれ1つずつ実行します。BIOSでハイパースレッディングを無効にすることができます。

そうは言っても、ハイパースレッディングを試してみても問題の解決には役立ちません。すでに述べたように実行し、リリースビルドのプロファイルを作成する必要があります。また、イベントログで奇妙なエラーを探します。また、sysinternalのProcess Explorerを実行して、I/Oに時間がかかりすぎていないかどうかを確認します。誰が知っているか、おそらくリリースビルドは、このマシンのデバイスドライバーで何らかの奇妙な動作を引き起こしています。

編集:これがIntelの技術説明(yay Wikipedia)で、実際には2002年のものです:http: //download.intel.com/technology/itj/2002/volume06issue01/vol6iss1_hyper_threading_technology.pdf

于 2012-09-07T13:50:45.410 に答える