我应该为“延迟临界”使用线程关联吗?线程

本文关键字:线程 关联 延迟临界 延迟 我应该 | 更新日期: 2023-09-27 18:02:51

在我的高频交易应用程序中,我有几个地方从网络接收数据。在大多数情况下,这只是一个只接收和处理数据的线程。下面是该处理的一部分:

    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上,如果这很重要的话,但是我认为我的问题更多的是关于硬件而不是语言或操作系统。

我应该为“延迟临界”使用线程关联吗?线程

我认为尽可能少延迟的算法是将你的线程固定在一个核心上,并将它们设置为实时优先级(或任何最高的优先级)。

这将导致操作系统驱逐任何碰巧使用该内核的其他线程。

希望CPU缓存仍然包含有用的数据,当你的线程被调度在那里。因为这个原因,我喜欢把它钉在一个核心上。

您应该将整个进程设置为高优先级类,并尽量减少机器上的其他活动。还要关闭未使用的硬件,因为它可能会产生中断。修复你的网卡的中断到一个不同的CPU核心(一些更好的网卡可以做到这一点)。

由于我想避免上下文切换,我最好在相同的处理器核心上运行相同的线程,对吗?

。将关联设置为一个CPU不一定可以避免上下文切换。您无法控制上下文切换,它们掌握在操作系统线程调度器的手中。当线程量(时间片)耗尽或更高优先级的线程中断您的线程时,它们会发生。

你所说的延迟,我假设是网络或内存延迟,根本不能通过设置线程亲和性来避免。内存延迟可以通过使代码缓存友好来避免(例如,它可以全部在L1 - L2缓存中)。网络延迟实际上是任何网络的一部分,我认为您对此无能为力。

既然狮子托尼已经回答了你的问题,我想谈谈你的评论:

"为什么不设置线程关系到我的代码?为什么我的例子中的线程需要在内核之间移动?"

你的线程没有移动到任何地方。

当OS线程调度器决定给你的线程一段时间来执行时,就会发生上下文切换。然后为线程准备好环境,例如CPU寄存器设置为正确的值等。这叫做上下文切换。

所以不管线程的亲缘关系如何,同样的CPU设置工作必须完成,无论是在你的线程运行时在上一个切片中使用的相同的CPU/核心还是另一个。在这个时刻,你的计算机有更多的信息来正确地完成它,而不是你在编译时做的。

你似乎认为线程以某种方式驻留在CPU上,但事实并非如此。您使用的是一个逻辑线程,可以有数百甚至数千个逻辑线程。普通的cpu, OTOH,通常每个核心有1或2个硬件线程,并且您的逻辑线程每次被调度时都会映射到其中一个,即使操作系统总是选择相同的硬件线程。

编辑:看来你已经选择了你想听到的答案,我不喜欢长时间的讨论,所以我把它放在这里。
    你应该试着测量一下。我相信你会失望的。
  • 在高优先级线程上运行一些线程可能很容易扰乱其他进程
  • 你担心上下文切换延迟,但你没有问题,GC线程会冻结你的线程?顺便说一句,你的GC线程将在哪个核心上运行?:)
  • 如果你的最高优先级线程阻塞了GC线程怎么办?内存泄漏?你知道线程的优先级是什么,所以你确定它会工作吗?
  • 如果微秒很重要,为什么不使用C或手工优化的汇编呢?
  • 就像有人建议的那样,如果你想控制这方面的执行,你应该使用RTOS
  • 你的数据在数据中心的传输速度似乎不太可能比在一台机器上设置线程上下文慢4-5倍,但是谁知道呢…