4

私のHFT取引アプリケーションには、ネットワークからデータを受信する場所がいくつかあります。ほとんどの場合、これはデータを受信して​​処理するだけのスレッドです。以下はそのような処理の一部です:

    public Reciver(IPAddress mcastGroup, int mcastPort, IPAddress ipSource)
    {

        thread = new Thread(ReceiveData);

        s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        s.ReceiveBufferSize = ReceiveBufferSize;

        var ipPort = new IPEndPoint(LISTEN_INTERFACE/* IPAddress.Any*/, mcastPort);
        s.Bind(ipPort);

        option = new byte[12];
        Buffer.BlockCopy(mcastGroup.GetAddressBytes(), 0, option, 0, 4);
        Buffer.BlockCopy(ipSource.GetAddressBytes(), 0, option, 4, 4);
        Buffer.BlockCopy(/*IPAddress.Any.GetAddressBytes()*/LISTEN_INTERFACE.GetAddressBytes(), 0, option, 8, 4);
    }

    public void ReceiveData()
    {
        byte[] byteIn = new byte[4096];
        while (needReceive)
        {
            if (IsConnected)
            {
                int count = 0;
                try
                {
                    count = s.Receive(byteIn);
                }
                catch (Exception e6)
                {
                    Console.WriteLine(e6.Message);
                    Log.Push(LogItemType.Error, e6.Message);
                    return;
                }
                if (count > 0)
                {
                    OnNewMessage(new NewMessageEventArgs(byteIn, count));
                }
            }
        }
    }

このスレッドは、一度作成されると永久に機能します。このスレッドを特定のコアで実行するように構成する必要があるかどうか疑問に思いますか?最小のレイテンシが必要なので、コンテキストスイッチを避けたいと思います。コンテキストスイッチを避けたいので、同じプロセッサコアで同じスレッドを実行する方が良いでしょう?

私が最低のレイテンシーを必要としていることを考慮に入れると、それは正しいです:

  • 「長時間実行」スレッドの大部分に「スレッドアフィニティ」を設定する方がよいでしょうか。
  • 上記の例のスレッドに「スレッドアフィニティ」を設定する方がよいでしょうか。

上記のコードを今すぐc++に書き直して、これが重要な場合は後でLinuxに移植しますが、私の質問は言語やOSよりもハードウェアに関するものだと思います。

4

3 に答える 3

2

レイテンシーをできるだけ少なくするアルゴリズムは、スレッドを1つのコアに固定し、それらをリアルタイムの優先度(または最も高いもの)に設定することだと思います。

これにより、OSはそのコアを使用する他のスレッドを削除します。

うまくいけば、スレッドがそこでスケジュールされたときに、CPUキャッシュに有用なデータがまだ含まれているはずです。そのため、コアに固定するというアイデアが好きです。

おそらく、プロセス全体を優先度の高いクラスに設定し、ボックス上の他のアクティビティを最小限に抑える必要があります。また、割り込みが発生する可能性があるため、未使用のハードウェアをオフにしてください。NICの割り込みを別のCPUコアに修正します(より優れたNICの中にはそれを実行できるものもあります)。

于 2013-03-08T14:17:13.833 に答える
1

コンテキストスイッチを避けたいので、同じプロセッサコアで同じスレッドを実行する方が良いでしょう?

いいえ。1つのCPUにアフィニティを設定しても、コンテキストスイッチは必ずしも回避されません。コンテキストスイッチを制御することはできません。コンテキストスイッチはOSスレッドスケジューラの管理下にあります。これらは、スレッドクォンタム(タイムスライス)が経過したとき、または優先度の高いスレッドがスレッドに割り込んだときに発生します。

あなたが話しているレイテンシーは、ネットワークまたはメモリーのレイテンシーだと思いますが、スレッドアフィニティを設定することでまったく回避できません。コードキャッシュを使いやすくすることで、メモリの待ち時間を回避できます(つまり、すべてをL1-L2キャッシュに含めることができます)。ネットワーク遅延は、実際にはネットワークの一部にすぎず、多くのことができるとは思えません。

于 2013-03-08T13:52:35.940 に答える
1

トニー・ライオンはすでにあなたの質問に答えているので、私はあなたのコメントに対処したいと思います:

「コードにスレッドの親和性を設定しないのはなぜですか?私の例のスレッドがコア間を移動する必要があるのはなぜですか?」

あなたのスレッドはどこにも移動しません。

コンテキストスイッチは、OSスレッドスケジューラがスレッドに実行時間を与えることを決定したときに発生します。次に、スレッド用の環境が準備されます。たとえば、CPUレジスタが正しい値に設定されるなどです。これは、コンテキストスイッチと呼ばれます。

したがって、スレッドの親和性に関係なく、スレッドの実行中に前のスライスで使用されたのと同じCPU /コアであるか、別のスライスであるかにかかわらず、同じCPUセットアップ作業を実行する必要があります。そして現時点では、コンパイル時に行うよりも、コンピュータに適切に行うための情報があります。

あなたはスレッドがどういうわけかCPUにあると信じているようですが、そうではありません。使用するのは論理スレッドであり、数百または数千ものスレッドが存在する可能性があります。一般的なCPUであるOTOHには、通常、コアごとに1つまたは2つのハードウェアスレッドがあり、OSが常に同じHWスレッドを選択する場合でも、論理スレッドはスケジュールされるたびにこれらの1つにマップされます。

編集:あなたはあなたが聞きたい答えをすでに選んだようです、そして私は答えに関する長い議論のスレッドが好きではないので、私はそれをここに置きます。

  • あなたはそれを試して測定する必要があります。がっかりすると思います
  • 優先度の高いスレッドで一部のスレッドを実行すると、他のプロセスが簡単に台無しになる可能性があります
  • コンテキストスイッチのレイテンシーが心配ですが、GCスレッドがスレッドをフリーズするという問題はありませんか?ところで、GCスレッドはどのコアで実行されますか?:)
  • 最も優先度の高いスレッドがGCスレッドをブロックした場合はどうなりますか?メモリリーク?そのスレッドの優先順位を知っているので、それが機能すると確信していますか?
  • 本当に、マイクロ秒が重要な場合は、Cまたは手動で最適化されたアセンブリを使用しないのはなぜですか?
  • 誰かが提案したように、実行のこの側面を制御したい場合は、RTOSを使用する必要があります
  • データがデータセンターを通過する速度は、1台のマシンでスレッドコンテキストを設定する場合よりも4〜5倍遅いとは思われませんが、誰が知っていますか...
于 2013-03-08T14:18:54.147 に答える