标签: numa

Linux上的memcpy性能不佳

我们最近购买了一些新的服务器,并且正在经历糟糕的memcpy性能.与我们的笔记本电脑相比,服务器上的memcpy性能要慢3倍.

服务器规格

  • 底盘和Mobo:SUPER MICRO 1027GR-TRF
  • CPU:2x Intel Xeon E5-2680 @ 2.70 Ghz
  • 内存:8x 16GB DDR3 1600MHz

编辑:我也在另一台具有更高规格的服务器上进行测试,并看到与上述服务器相同的结果

服务器2规格

  • 底盘和Mobo:SUPER MICRO 10227GR-TRFT
  • CPU:2x Intel Xeon E5-2650 v2 @ 2.6 Ghz
  • 内存:8x 16GB DDR3 1866MHz

笔记本电脑规格

  • 机箱:联想W530
  • CPU:1x Intel Core i7 i7-3720QM @ 2.6Ghz
  • 内存:4x 4GB DDR3 1600MHz

操作系统

$ cat /etc/redhat-release
Scientific Linux release 6.5 (Carbon) 
$ uname -a                      
Linux r113 2.6.32-431.1.2.el6.x86_64 #1 SMP Thu Dec 12 13:59:19 CST 2013 x86_64 x86_64 x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)

编译器(在所有系统上)

$ gcc --version
gcc (GCC) 4.6.1 …
Run Code Online (Sandbox Code Playgroud)

c c++ linux memcpy numa

69
推荐指数
3
解决办法
1万
查看次数

测量NUMA(非统一内存访问).没有可观察到的不对称性.为什么?

我试图测量NUMA的非对称内存访问效果,但都失败了.

本实验

采用Intel Xeon X5570 @ 2.93GHz,2个CPU,8个内核.

在固定到核心0的线程上,我使用numa_alloc_local在核心0的NUMA节点上分配大小为10,000,000字节的数组x.然后我迭代数组x 50次并读取和写入数组中的每个字节.测量进行50次迭代所用的时间.

然后,在我的服务器中的每个其他核心上,我固定一个新线程并再次测量经过50次迭代读取和写入数组x中每个字节的时间.

数组x很大,可以最大限度地减少缓存效 我们想要测量CPU必须一直到RAM加载和存储的速度,而不是在缓存有帮助的时候.

我的服务器中有两个NUMA节点,因此我希望在分配了数组x的同一节点上具有亲缘关系的核心具有更快的读/写速度.我没有看到.

为什么?

也许NUMA仅与8-12核心的系统相关,正如我在别处看到的那样?

http://lse.sourceforge.net/numa/faq/

numatest.cpp

#include <numa.h>
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <pthread.h>

void pin_to_core(size_t core)
{
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(core, &cpuset);
    pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
}

std::ostream& operator<<(std::ostream& os, const bitmask& bm)
{
    for(size_t i=0;i<bm.size;++i)
    {
        os << numa_bitmask_isbitset(&bm, i);
    }
    return os;
}

void* thread1(void** x, size_t core, size_t N, size_t M)
{
    pin_to_core(core);

    void* y …
Run Code Online (Sandbox Code Playgroud)

c++ linux performance linux-kernel numa

33
推荐指数
5
解决办法
9114
查看次数

在NUMA架构上可扩展分配大型(8MB)内存区域

我们目前正在使用TBB流程图,其中a)并行过滤器处理数组(与偏移并行)并将处理结果放入中间向量(在堆上分配;大多数向量将增长到8MB).然后将这些矢量传递给节点,然后节点根据它们的特性(在a中确定)对这些结果进行后处理.由于资源同步,每个特征只能有一个这样的节点.我们编写的原型在UMA架构上运行良好(在单CPU Ivy Bridge和Sandy Bridge架构上测试).但是,该应用程序无法在我们的NUMA架构(4 CPU Nehalem-EX)上扩展.我们将问题归结为内存分配并创建了一个最小的示例,其中我们有一个并行管道,它只是从堆中分配内存(通过8MB块的malloc,然后memset 8MB区域;类似于初始原型所做的)达到一定的记忆力.我们的发现是:

  • 在UMA架构上,应用程序与管道使用的线程数呈线性关系(通过task_scheduler_init设置)

  • 在NUMA架构上,当我们将应用程序固定到一个插槽(使用numactl)时,我们看到相同的线性放大

  • 在我们使用多个套接字的NUMA架构中,我们的应用程序运行的时间随着套接字的数量而增加(负线性比例 - "向上")

对我们来说,这就像堆争用一样.我们到目前为止尝试的是将英特尔的TBB可扩展分配器替换为glibc分配器.但是,单个套接字上的初始性能比使用glibc更差,在多个套接字上性能不会变差但也没有变得更好.我们使用tcmalloc,hoard分配器和TBB的缓存对齐分配器获得了相同的效果.

问题是,是否有人遇到类似的问题.堆栈分配对我们来说不是一个选项,因为我们希望在管道运行后保持堆分配的向量.一个堆如何在多个线程的NUMA体系结构上有效地分配MB大小的内存区域?我们真的希望保持动态分配方法,而不是预先分配内存并在应用程序中管理内存.

我用numactl为各种执行附加了perf stats.Interleaving/localalloc无任何影响(QPI总线不是瓶颈;我们通过PCM验证,QPI链路负载为1%).我还添加了一个描绘glibc,tbbmalloc和tcmalloc结果的图表.

perf stat bin/prototype 598.867

'bin/prototype'的性能计数器统计信息:

  12965,118733 task-clock                #    7,779 CPUs utilized          
        10.973 context-switches          #    0,846 K/sec                  
         1.045 CPU-migrations            #    0,081 K/sec                  
       284.210 page-faults               #    0,022 M/sec                  
17.266.521.878 cycles                    #    1,332 GHz                     [82,84%]
15.286.104.871 stalled-cycles-frontend   #   88,53% frontend cycles idle    [82,84%]
10.719.958.132 stalled-cycles-backend    #   62,09% backend  cycles idle    [67,65%]
 3.744.397.009 instructions              #    0,22  insns per cycle        
                                         #    4,08  stalled cycles per insn [84,40%]
   745.386.453 branches …
Run Code Online (Sandbox Code Playgroud)

c++ parallel-processing memory-management tbb numa

22
推荐指数
2
解决办法
1856
查看次数

我怎么知道我的服务器是否有NUMA?

从Java Garbage Collection跳转,我遇到了NUMA的JVM设置.奇怪的是我想检查我的CentOS服务器是否具有NUMA功能.是否有可以获取此信息的*ix命令或实用程序?

linux kernel jvm processor numa

18
推荐指数
5
解决办法
3万
查看次数

Windows上的多线程Java应用程序的CPU使用率太低

我正在开发一个Java应用程序,用于解决一类数值优化问题-更确切地说是大规模线性编程问题。单个问题可以分解为多个较小的子问题,这些子问题可以并行解决。由于子问题多于CPU内核,因此我使用ExecutorService并将每个子问题定义为可提交给ExecutorService的Callable。解决子问题需要调用本机库-在这种情况下为线性编程求解器。

问题

我可以在Unix和具有多达44个物理内核和256g内存的Windows系统上运行该应用程序,但是在Windows上,大问题的计算时间比Linux上高一个数量级。Windows不仅需要大量内存,而且随着时间的推移,CPU利用率从开始时的25%下降到几个小时后的5%。这是Windows中任务管理器的屏幕截图:

任务管理器CPU利用率

观察结果

  • 整个问题的大型实例的解决时间从数小时到数天不等,最多消耗32g的内存(在Unix上)。子问题的解决时间在ms范围内。
  • 对于仅需几分钟即可解决的小问题,我不会遇到此问题。
  • Linux开箱即用地使用了两个套接字,而Windows要求我显式地激活BIOS中的内存交错,以便应用程序利用两个内核。但是,是否执行此操作不会对总体CPU利用率随时间的下降造成影响。
  • 当我查看VisualVM中的线程时,所有池线程都在运行,没有一个正在等待。
  • 根据VisualVM,90%的CPU时间用于本机函数调用(解决一个小的线性程序)
  • 垃圾回收不是问题,因为该应用程序不会创建和取消引用很多对象。而且,大多数内存似乎是堆外分配的。对于最大实例,Linux上4g的堆足够,而Windows上8g的堆就足够了。

我尝试过的

  • 各种JVM参数,高XMS,高元空间,UseNUMA标志和其他GC。
  • 不同的JVM(热点8、9、10、11)。
  • 不同线性编程求解器(CLP,Xpress,Cplex,Gurobi)的不同本机库。

问题

  • 是什么导致大量使用本地调用的大型多线程Java应用程序在Linux和Windows之间的性能差异?
  • 在实现方面有什么可以改变的,例如Windows,我是否应该避免使用会接收成千上万个Callable的ExecutorService来代替呢?

java java-native-interface multithreading jvm-hotspot numa

18
推荐指数
1
解决办法
369
查看次数

NUMA机器上的共享库瓶颈

我正在使用NUMA机器(SGI UV 1000)同时运行大量数值模拟,每个模拟都是使用4个核心的OpenMP作业.但是,运行超过100个这样的工作会导致性能受到重大影响.我们关于为什么会发生这种情况的理论是,软件所需的共享库只被加载到机器的全局内存中一次,然后系统就会遇到通信瓶颈,因为所有进程都访问单个节点上的内存.

它是一个旧的软件,无限制修改范围,静态make选项不会静态链接所需的所有库.从我所看到的最方便的解决方案是以某种方式迫使系统在每个进程或节点上加载所需共享库的新副本(在每个进程或节点上运行3个进程),但我没有能够找到如何做到这一点.任何人都可以告诉我如何做到这一点,或有任何其他建议如何解决这个问题?

linux hpc shared-libraries linux-kernel numa

13
推荐指数
1
解决办法
1625
查看次数

-XX:+ UseNUMA如何影响只有一个节点的系统的JVM性能?

关于JVM NUMA感知分配器的好处有很多文章.但是,我无法找到有关性能影响可能导致-XX:+UseNUMA单节点拓扑标记的信息,例如

# numactl --hardware
available: 1 nodes (0)
node 0 cpus: 0 1 2 3
node 0 size: 32060 MB
node 0 free: 7770 MB
node distances:
node   0 
  0:  10
Run Code Online (Sandbox Code Playgroud)

这似乎是一种极端情况,并且在启用标志方面没有实际利润.如果是这样,启用它可能会导致任何缺点吗?

java performance jvm numa

13
推荐指数
1
解决办法
3789
查看次数

您的内核可能是在没有 NUMA 支持的情况下构建的

我有 Jetson TX2、python 2.7、Tensorflow 1.5、CUDA 9.0

Tensorflow 似乎工作正常,但每次运行该程序时,我都会收到此警告:

with tf.Session() as sess:
    print (sess.run(y,feed_dict))
Run Code Online (Sandbox Code Playgroud)

...

2018-08-07 18:07:53.200320: E tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:881] could not open file to read NUMA node: /sys/bus/pci/devices/0000:00:00.0/numa_node Your kernel may have been built without NUMA support.

2018-08-07 18:07:53.200427: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1105] Found device 0 with properties:

name: NVIDIA Tegra X2
major: 6 
minor: 2 
memoryClockRate(GHz): 1.3005

pciBusID: 0000:00:00.0

totalMemory: 7.66GiB 
freeMemory: 1.79GiB

2018-08-07 18:07:53.200474: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1195] Creating TensorFlow device (/device:GPU:0) -> (device: 0, name: NVIDIA Tegra X2, pci bus id: …
Run Code Online (Sandbox Code Playgroud)

linux-kernel numa tensorflow

13
推荐指数
1
解决办法
3万
查看次数

多线程:为什么两个程序比一个好?

关于我的问题:

我有一台带有2个AMD Opteron 6272和64GB RAM插槽的电脑.

我在所有32个核心上运行一个多线程程序,与运行2个程序的情况相比,速度降低了15%,每个程序在一个16核心插槽上运行.

如何以两个程序的速度制作单程序版本?


更多细节:

我有大量的任务,并希望完全加载系统的所有32个核心.因此,我将任务分组打包1000个.这样的组需要大约120Mb的输入数据,并且需要大约10秒才能在一个核心上完成.为了使测试更加理想,我将这些组复制32次,并使用ITBB的parallel_for循环在32个核心之间分配任务.

pthread_setaffinity_np用来确保系统不会让我的线程在核心之间跳转.并确保所有核心都得到了相应的使用.

mlockall(MCL_FUTURE)用来确保系统不会让我的内存在套接字之间跳转.

所以代码看起来像这样:

  void operator()(const blocked_range<size_t> &range) const
  {
    for(unsigned int i = range.begin(); i != range.end(); ++i){

      pthread_t I = pthread_self();
      int s;
      cpu_set_t cpuset;
      pthread_t thread = I;
      CPU_ZERO(&cpuset);
      CPU_SET(threadNumberToCpuMap[i], &cpuset);
      s = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);

      mlockall(MCL_FUTURE); // lock virtual memory to stay at physical address where it was allocated

      TaskManager manager;
      for (int j = 0; j < fNTasksPerThr; j++){
        manager.SetData( &(InpData->fInput[j]) …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading pthreads numa

12
推荐指数
1
解决办法
424
查看次数

为什么我的.Net应用程序只使用单个NUMA节点?

我有一台带有2个NUMA节点的服务器,每个节点有16个CPU.我可以看到任务管理器中的所有32个CPU,前2行中的前16个(NUMA节点1)和后2行中的后16个(NUMA节点2).

在我的应用程序中,我开始使用64个线程Thread.Start().当我运行应用程序时,它是CPU密集型的,只有前16个CPU处于忙碌状态,其他16个CPU处于空闲状态.

为什么?我使用Interlocked.Increment()了很多.这可能是个原因吗?有没有办法在特定的NUMA节点上启动线程?

.net c# multithreading numa

12
推荐指数
2
解决办法
2200
查看次数