Visual c++ Windows桌面在繁重的网络I/O/Windows内核只分配1个CPU时瘫痪?

Visual c++ Windows桌面在繁重的网络I/O/Windows内核只分配1个CPU时瘫痪?,visual-c++,network-programming,multicore,windows-kernel,cpu-load,Visual C++,Network Programming,Multicore,Windows Kernel,Cpu Load,问题:我们在Windows Server 2012系统上实现了一个视频录制系统。尽管CPU和内存消耗较低,但我们仍面临严重的性能问题 简短的程序描述:应用程序(VS2005/C++)创建许多网络套接字,每个套接字从以太网网络接收多播UDP视频流。对于每个流,应用程序通过调用WSARecvFrom()(重叠操作)提供一个接收器缓冲区,在MsgWaitForMultipleObjects()中等待窗口的“数据到达”事件,获取数据包,并在无休止的循环中再次重复所有操作。对于测试,为了确保除了纯套接字I

问题:我们在Windows Server 2012系统上实现了一个视频录制系统。尽管CPU和内存消耗较低,但我们仍面临严重的性能问题

简短的程序描述:应用程序(VS2005/C++)创建许多网络套接字,每个套接字从以太网网络接收多播UDP视频流。对于每个流,应用程序通过调用WSARecvFrom()(重叠操作)提供一个接收器缓冲区,在MsgWaitForMultipleObjects()中等待窗口的“数据到达”事件,获取数据包,并在无休止的循环中再次重复所有操作。对于测试,为了确保除了纯套接字IO工作之外,CPU和内存消耗最小,应用程序不执行任何操作,也不执行任何磁盘/文件IO。应用程序进程配置为使用计算机上的所有可用内核(默认关联设置不变)

测试运行:该测试在两台不同的计算机上运行:a)具有4个物理内核/8个超线程的Windows 7,以及b)具有12个物理内核/24个超线程的Windows Server 2012

两个系统都显示出相同的问题:在配置了一定数量的套接字/网络流之后,一切都可以正常工作。进一步增加它们(我们需要)最终会使Windows桌面瘫痪(鼠标指针、重新绘制)。在此阶段,总CPU负载仍然很低(即10-15%),并且有很多可用内存。但是任务管理器显示了非常片面的CPU负载:CPU 0接近100%,所有其他CPU接近0%。在任务管理器中更改进程的处理器相关性没有帮助

问题1:看起来CPU 0正在完成整个内核的网络IO工作。有可能吗

问题2:如果是,有没有办法控制内核对可用CPU的使用?如果是,如何进行

问题3:如果没有,是否有其他方法使Windows将(内核)网络IO分配给其他CPU(即安装多个NIC卡,每个NIC只接收网络流的一个子集,并将每个NIC绑定到另一个CPU)


非常感谢任何人给我的提示。

我不是一个Windows服务器的家伙,但这听起来像是一个中断问题。这通常发生在高吞吐量系统中,尤其是实时系统

背景:

简单地说,对于每个数据包,您的网络接口都会生成一个中断,通知CPU它需要处理新到达的数据。接收小数据包的高通量网卡(如10Gbps)很容易因这些中断而使CPU无法工作

为了了解这个问题,让我们做一些数学计算——如果你用100字节的数据包使10G线路饱和,这意味着(理想情况下)每秒通过线路发送12500000个数据包。事实上,这不是由于管理费用造成的;比如每秒10000000包(pps)。您的3Ghz cpu每秒生成3000000000个时钟。所以它需要每300个时钟周期处理一个数据包。这对于一台通用机器来说相当困难

现在,我不知道您的数据包到达率,也不知道您的平均数据包长度。但是根据你描述的症状,你可能遇到了这个问题

解决方案

  • 将工作转移到您的卡上
  • 现代网络卡,尤其是高吞吐量的网络卡,支持各种有用的卸载,如、和其他。这些方法将一些与网络相关的工作从CPU上移除(如校验和计算、数据包碎片化等),并将其放到网卡上,网卡上装有专用硬件来执行这些工作。查看您的卡支持的卸载。在Linux中,使用名为ethtool的应用程序执行卸载管理。因为我从来没有在windows中玩过卸载,所以我只能指出这个方向,但我不能提供任何基于经验的建议

  • 使用。
  • 中断节流是(某些)网卡及其驱动程序的另一种功能,允许它们限制CPU接收的中断次数,本质上是每隔几个数据包中断核心一次,而不是每数据包中断一次

  • 使用多队列网卡,并设置中断相关性。

  • 有些网卡有多个(数据包)队列,因此有多条中断线,每个队列一条。它们使用散列函数在队列之间均匀地分割传入流量,以1/8或1/16的线速率创建(通常)8或16个流。每个流都可以使用中断关联绑定到特定的CPU核心,并且由于哈希函数是根据IP和端口号计算的,并且具有确定性,因此每个TCP/IP级别的会话将始终由同一个核心处理。在Linux中,设置亲缘关系需要写入
    /proc/irq//smp\u affinity
    。在windows中,似乎就是这样

    这是一个环境问题,每一个过程似乎都遇到了隐藏在某处的锁。最可能的原因是安全软件,如反恶意软件或防火墙。我在AWS EC2实例上运行Windows Server 2012 R2时遇到了非常类似的问题。切换到Windows Server 2016后,我得到了非常显著的改进。我怀疑,如本文所述,只要从Intel driver 1.0.15.3升级,就可以实现类似的改进