当前位置: 首页 > 知识库问答 >
问题:

多线程降低了NUMA上的套接字吞吐量

邵昆琦
2023-03-14

我在一台16核NUMA机器上用Red Had Linux对一个Java程序进行了基准测试。我测量了Java DatagramSocket(用于UDP)的吞吐量,即每秒能够接收和发送多少数据包(64字节大小)。这个程序由一个套接字和n个监听套接字的线程组成。当数据包到达时,它们会将有效负载复制到byte[]数组中,用该数组创建一个新的DatagramPacket,并直接将其发送回它的来源。可以把它想象成UDP层上的ping。

>

  • 我发现,当使用多个线程(即两个或四个线程)时,Java DatagramSocket套接字的吞吐量要小得多。如果我只使用一个线程侦听套接字,那么我的吞吐量为每秒122000个数据包,而多个线程的吞吐量仅为每秒65000个数据包。现在,我知道线程可能会在NUMA机器的任何核心上执行,如果内存必须从一个节点传输到另一个节点,那么内存访问就会变得昂贵。然而,如果我有两个线程,那么只有一个线程应该在“错误”的内核上执行,而另一个线程仍然应该实现非常高的吞吐量。另一种可能的解释是Datagramsocket中的同步问题,但这些只是猜测。有人对真正的解释有很好的洞察力吗?

    我发现在多个端口上多次(并行)执行此程序可以实现更高的总体吞吐量。我用一个线程启动了四次程序,每个程序在单独的端口(5683,5684,5685和5686)上使用套接字。这四个程序的总吞吐量为每秒 370,000 个数据包。总之,在同一端口上使用多个线程会降低吞吐量,而使用多个端口和一个线程会增加吞吐量。这怎么能解释呢?

    系统规格:

    硬件:2个AMD Opteron(TM)处理器6212处理器上的16个内核组织在4个节点中,每个节点具有32 GB RAM。频率:1.4 Ghz,2048 KB缓存。

    node distances:
    node   0   1   2   3
      0:  10  16  16  16
      1:  16  10  16  16
      2:  16  16  10  16
      3:  16  16  16  10
    

    操作系统是Red Hat Enterprise Linux工作站版本6.4 (Santiago),内核版本< code > 2 . 6 . 32-358 . 14 . 1 . el6 . x86 _ 64 。Java版本< code >“1 . 7 . 0 _ 09”,Java(TM) SE运行时环境(< code>build 1.7.0_09-b05),Java HotSpot(TM) 64位服务器VM (build 23.5-b02,混合模式),我使用了< code>-XX: UseNUMA标志。服务器和客户端通过10GB以太网连接。

  • 共有1个答案

    戈巴英
    2023-03-14

    一般来说,只使用一个线程时效率最高。将东西并行化将不明显地引入成本。只有当您可以并行执行的额外工作量超过此成本时,吞吐量的增加才会出现。

    现在,阿姆达尔定律说明了吞吐量的理论增长与您的工作中有多少可以并行化/不能并行化有关。例如,如果您的任务只有50%是可并行化的,那么无论您在问题上投入多少线程,您都只能获得2倍的吞吐量增长。请注意,您在链接中看到的图表忽略了添加线程的成本。实际上,本机操作系统线程确实会增加相当多的成本,尤其是当许多线程试图访问共享资源时。

    在您的例子中,当您只使用一个套接字时,大多数工作都不可并行化。因此,使用单个线程可以获得优异的性能,而添加线程会因为增加成本而使性能变得更差。在第二个实验中,通过使用多个套接字增加了可以并行处理的工作量。因此,尽管使用线程增加了一些成本,但您还是获得了吞吐量。

     类似资料:
    • 我为帖子的篇幅感到抱歉,但有很多事情可能会导致我的情况,我已经尝试将我根据其他帖子所做的所有设置更改包括在内。简言之,我的WCF服务似乎一次只能处理3到4个并发客户端请求。如果我将应用程序池最大工作进程数设置得更高(大约10个),或者将服务行为ConcurrencyMode设置为多个,那么吞吐量就会大大提高(快几倍)。然而,这些似乎是真正问题的解决办法,带来了他们自己的问题。是我错了,还是IIS应

    • 我想通过从CSV文件向服务器发送100个请求来测试10个线程。我想每个线程按顺序发射100个请求,同时允许并行请求。我有我的主要采样器和子采样器的子组件和另一个采样器,我想比较我的结果。这种配置通常会产生7个采样器。问题是,当我尝试绘制吞吐量与线程之间的关系图时,在1个用户中,结果在y轴上显示了100多个事务/秒的值。同样的事情发生在“显示结果表”侦听器(即,对于1个用户,它显示700个样本)如何

    • 这是我的客户端和服务器的代码。 class Client1{Client1(int no){try{String message;message=“Hello this is client”+no;byte[]b=message.getBytes();DatagramPacket dp=new DatagramPacket(b,b length,inetAddress.getLocalHost()

    • 我有一个类似的问题,但是我知道当我要求阅读一行时,发件人应该发送一个行尾。 让我困惑的是,在调试中,它是有效的。可能是因为我在调试时跳过的顺序(直到现在我都不知道这会有什么不同),但我想更好地理解它。 我已经使用线程,但不是很多。 这是我的服务器类: 线程(基于此) 和客户: 它似乎在某个地方进入了死锁,出于某种原因,除非在调试中运行,否则永远不要在向客户端发送数据的服务器类上输入该死锁 (顺便说

    • 我正在为移动机器开发一个服务器,该服务器使用Visual Studio Express 2013实现套接字服务器以接收其连接。 它使用将连接分配给一个。它为每个创建的新套接字启动一个新的,并有一个while周期来接收、解析和写入数据到套接字。它使用属性获取数据计数,并使用

    • 我已经在Google云中设置了Jmeter 4.0,其中一个主服务器与12个从服务器对话以生成负载。对于非常少的线程,测试就像一个魔咒,在最后生成报告。 然而,当我将每个从属主机的线程数增加到200以上时,测试似乎挂起了,我在服务器端没有看到很多请求。在上升期之后,我看不到持续超过5分钟的活动,它在那之后慢慢变小。我可以用数据库计数来验证——上升期结束后,比率下降了很多。在30分钟测试结束时,只有