使用单核与2+核时,页面错误数是10倍

时间:2018-05-07 12:41:24

标签: python linux numpy multiprocessing page-fault

我正在观察我在Linux下使用Python 3.6 / Numpy开发的并行代码中的奇怪行为:在2个内核上运行它比在单个内核上运行它快3倍。我不确定我是否理解确切的问题,但我设法找到了一些线索:

  1. 使用perf我发现我使用一个核心而不是两个核心来获得更多页面错误(部分运行是长期运行的作业):
  2. 1核心

       57414.449252      task-clock:u (msec)       #    1.000 CPUs utilized          
                  0      context-switches:u        #    0.000 K/sec                  
                  0      cpu-migrations:u          #    0.000 K/sec                  
         22,583,368      page-faults:u             #    0.393 M/sec                  
    115,569,738,160      cycles:u                  #    2.013 GHz                    
     22,655,695,268      stalled-cycles-frontend:u #   19.60% frontend cycles idle   
     32,251,136,400      stalled-cycles-backend:u  #   27.91% backend cycles idle    
    189,041,318,733      instructions:u            #    1.64  insn per cycle         
                                                   #    0.17  stalled cycles per insn
     38,298,469,811      branches:u                #  667.053 M/sec                  
        654,389,291      branch-misses:u           #    1.71% of all branches        
     83,343,166,583      L1-dcache-loads:u         # 1451.606 M/sec                  
        318,284,548      L1-dcache-load-misses:u   #    0.38% of all L1-dcache hits  
     25,589,478,853      L1-icache-loads:u         #  445.698 M/sec                  
      2,560,674,130      L1-icache-load-misses:u   #   10.01% of all L1-icache hits  
     83,377,552,384      dTLB-loads:u              # 1452.205 M/sec                  
        216,145,062      dTLB-load-misses:u        #    0.26% of all dTLB cache hits 
     25,626,979,550      iTLB-loads:u              #  446.351 M/sec                  
         55,847,490      iTLB-load-misses:u        #    0.22% of all iTLB cache hits 
            222,176      L1-dcache-prefetches:u    #    0.004 M/sec                  
            220,870      L1-dcache-prefetch-misses:u #    0.004 M/sec                
    

    2个核心

      111569.269846      task-clock:u (msec)       #    1.837 CPUs utilized         
                  0      context-switches:u        #    0.000 K/sec                 
                  0      cpu-migrations:u          #    0.000 K/sec                 
          4,415,116      page-faults:u             #    0.040 M/sec                 
    330,750,606,867      cycles:u                  #    2.965 GHz                   
     69,517,418,862      stalled-cycles-frontend:u #   21.02% frontend cycles idle  
    104,365,888,484      stalled-cycles-backend:u  #   31.55% backend cycles idle   
    609,338,385,634      instructions:u            #    1.84  insn per cycle        
                                                   #    0.17  stalled cycles per ins
    125,341,622,204      branches:u                # 1123.442 M/sec                 
      1,860,702,685      branch-misses:u           #    1.48% of all branches       
    261,941,396,767      L1-dcache-loads:u         # 2347.792 M/sec                 
        935,372,306      L1-dcache-load-misses:u   #    0.36% of all L1-dcache hits 
     79,306,212,694      L1-icache-loads:u         #  710.825 M/sec                 
      7,337,551,130      L1-icache-load-misses:u   #    9.25% of all L1-icache hits 
    261,578,594,355      dTLB-loads:u              # 2344.540 M/sec                 
        425,510,820      dTLB-load-misses:u        #    0.16% of all dTLB cache hits
     79,008,997,415      iTLB-loads:u              #  708.161 M/sec                 
        102,332,385      iTLB-load-misses:u        #    0.13% of all iTLB cache hits
            944,223      L1-dcache-prefetches:u    #    0.008 M/sec                 
            945,497      L1-dcache-prefetch-misses:u #    0.008 M/sec               
    
    1. 运行perf top表示在内核中花费了大约35%的时间,这些函数是最主要的贡献者:

      clear_page_rep
      page_fault
      check_preemption_disabled
      get_page_from_freelist
      __handle_mm_fault
      free_pcppages_bulk
      __pagevec_lru_add_fn
      sync_regs release_pages
      handle_mm_fault
      preempt_count_add

    2. 我似乎至少部分问题是在复制大约15×3500浮点数的Numpy数组时创建的,但不是每次都复制。该代码基本上在笛卡尔物理参数网格上计算模型,并对包含少量Numpy数组的对象进行频繁复制。现在,对于该对象的一些副本(但不是全部),这个~15×3500 Numpy数组的副本需要大约15倍的时间,我假设由于页面错误。代码经常创建/删除这些对象,但与每个进程关联的整体内存变化缓慢(结果写入共享的RawArray)所以我认为通常应该重新分配内存(在破坏后很快就会创建新对象)前一个)。只有在使用单个核心时才会发生这种情况,而不是在使用更多核心时。

    3. 我尝试同时使用1个核心启动两个独立的运行,并且它们都有大量的页面错误。所以它似乎与同时运行多个进程无关。

    4. 当在单核上运行时,我尝试了多处理(spawn和fork)而没有,结果是相同的,有大量的页面错误。所以它似乎没有相关性

    5. Archlinux python软件包和Anaconda软件包都会出现这种情况。

    6. 在具有512 GB或RAM的AMD EPYC 7351和具有64 GB RAM的Intel Core i7 6700K(均运行Archlinux)上都会出现这种情况。代码使用~10 GB的RAM,大多数以RawArrays的形式存储结果。单个对象中使用的RAM应该是每个对象大约500 kB,并且在任何给定时刻RAM中的RAM不应超过7-8。

    7. 我有点迷失为什么在单核上运行时会出现如此多的页面错误,而在2+核心上运行则不会。知道可能发生的事情和可能的解决方法吗?我正在尝试测量代码如何随核心数量而扩展,因此我希望在单核上运行时获得可靠的数据点。使用2个内核比在单个内核上运行快3倍。

0 个答案:

没有答案