2013-09-24 32 views
3

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

  1. 我发现使用多个线程(即两个或四个)时,Java DatagramSocket套接字实现的吞吐量要小得多。如果我仅使用一个线程来侦听套接字,则每秒的吞吐量为122,000个数据包,而多个线程每秒只能达到65,000个数据包。现在,我知道一个线程可能会在NUMA机器的任何核心上执行,并且如果内存必须从一个节点移动到另一个节点,那么内存访问会变得非常昂贵。但是,如果我有两个线程,则只有一个线程应该在“错误”的内核上执行,而另一个线程仍应该实现非常高的吞吐量。另一个可能的解释是Datagramsocket中的同步问题,但这只是猜测。有没有人对真正的解释有很好的认识?

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

系统规格:

设备:在4个节点与每个32 GB RAM组织16个核上2的AMD Opteron(TM)处理器6212的处理器。频率: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 

操作系统是红帽企业Linux工作站释放6.4(圣地亚哥)与内核版本2.6.32-358.14.1.el6.x86_64。 Java版本"1.7.0_09",Java TM SE运行时环境(build 1.7.0_09-b05),Java HotSpot TM 64位服务器VM(build 23.5-b02, mixed mode),并且我使用了-XX:+UseNUMA标志。服务器和客户端通过10GB以太网连接。

+2

您应该首先提供基准代码。 –

+1

我不明白你为什么要在非并行的网络上测试并行性。尝试使用多个线程写入单个磁盘时,您会得到类似的结果。 – Kayaman

+0

你能用4个不同的套接字测试4个线程吗?我的猜测是它会比4个线程/ 1个套接字好得多,但可能比4个进程/ 4个套接字略差。顺便说一下,'DatagramSocket.receive()'是'synchronized'。 – ninjalj

回答

1

一般而言,只使用一个线程时效率最高。将东西并行将不可避免地引入成本。吞吐量的增加只会在您可以并行执行的额外工作量超过此成本时才会增加。

现在,Amdahl's law说明了吞吐量的理论增益,相对于您的工作量由可并行/不能并行化的东西组成。例如,如果只有50%的任务可并行化,则无论有多少线程处理该问题,只能增加吞吐量x2。请注意,您在链接中看到的图表忽略了添加线程的成本。实际上,本地操作系统线程确实增加了相当多的成本和esp。当他们中的很多人试图访问共享资源时。

就你而言,当你只使用一个套接字时,你的大部分工作都是不可并行化的。因此,使用单个线程会提供更好的性能,添加线程会使其更糟糕,因为它们会增加成本。在第二个实验中,您增加了可以通过使用多个套接字进行并行化的工作。因此,尽管通过使用线程增加了一些成本,但您获得了吞吐量