设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

Nah Lock:一个无锁的内存分配器

2014-12-22 11:28| 发布者: joejoe0332| 查看: 4526| 评论: 0|原作者: gones945, daxiang, C梦, 无若, shines77|来自: oschina

摘要: 我实现了两个完全无锁的内存分配器:_nalloc 和 nalloc。 我用benchmark工具对它们进行了一组综合性测试,并比较了它们的指标值。与libc(glibc malloc)相比,第一个分配器测试结果很差,但是我从中学到了很多东西 ...

结果

在这之后,一段长时间的修改Bug,下面是,理论上完美并行,无移动工作负载,在64核机器上的性能表现,:

这样, __nalloc和ptmalloc表现的一样差 (并不想我描述的那么差). 下面是gperftools的样本配置在GHC* 6核上面的性能表现:

*(在ALADDIN机器上,我没有获取到 libunwind/gperftools的配置)


  下面是根据Linux perf得到的硬件计数器报告:


 Performance counter stats for './natest -t 6 -o 10000':

       690,482,105 L1-dcache-loads
        67,097,600 L1-dcache-misses
         #    9.72% of all L1-dcache hits   [26.08%]
       523,794,050 L1-dcache-stores
        22,848,232 L1-dcache-misses
         5,618,859 L1-dcache-prefetches
           377,630 L1-dcache-misses
        29,608,157 LLC-loads
        14,276,385 LLC-misses
               #   48.22% of all LL-cache hits    [21.63%]
        45,153,262 LLC-stores
         8,554,146 LLC-misses
         6,247,900 LLC-prefetches
         2,285,035 LLC-misses
               389 page-faults                                               
     6,665,279,571 cpu-cycles
     4,921,627,270 stalled-cycles-frontend   #   73.84% frontend cycles idle
     2,489,718,064 stalled-cycles-backend    #   37.35% backend  cycles idle
        24,771,227 branch-misses
        22,731,022 cache-misses              #   46.787 % of all cache refs
        48,583,721 cache-references
     3,711,376,010 instructions              #    0.56  insns per cycle
                                             #    1.33  stalled cycles per

       0.415147303 seconds time elapsed

和tcmalloc对比:

 Performance counter stats for './tctest.sh -t 6 -o 10000':

       691,325,411 L1-dcache-loads
        18,485,376 L1-dcache-misses
         #    2.67% of all L1-dcache hits   [27.18%]
       403,827,409 L1-dcache-stores
         6,107,731 L1-dcache-misses
         1,874,221 L1-dcache-prefetches
           397,279 L1-dcache-misses
         5,351,265 LLC-loads
           799,161 LLC-misses
               #   14.93% of all LL-cache hits    [23.60%]
        13,872,244 LLC-stores
         2,803,597 LLC-misses
            58,189 LLC-prefetches
             6,720 LLC-misses
            15,043 page-faults                                                 
     1,679,857,462 cpu-cycles
       566,843,996 stalled-cycles-frontend   #   33.74% frontend cycles idle    [23.33%]
       515,528,620 stalled-cycles-backend    #   30.69% backend  cycles idle    [23.07%]
         5,163,499 branch-misses          
         2,378,294 cache-misses              #   26.742 % of all cache refs     [22.54%]
         8,893,414 cache-references
     2,850,831,772 instructions              #    1.70  insns per cycle        
                                             #    0.20  stalled cycles per insn [27.57%]

       0.106878690 seconds time elapsed

  需要指出的是,Linux sysfs在目标机器(ghc29)报告说到,当L1和L2对每个物理核心是局部缓存的时候,LL/L3缓存是共享的.

__nalloc是有内存限制的. 它和tcmalloc一样,最多产生3.9x 的LLC引用,同时,最多导致6.3x的缺失.例如,对于每个free(), merge_adjacent()获取3个块头部,并插入到全局空闲链表.对于每个malloc(), shave获取3个块头部,并从空闲链表弹出.另一方面,tcmalloc的配置显示,它只是压入和弹出一个单链表.


  最值得说的细节是,L1数据缓存加载只有9%的缺失,而在LLC中缺失了48%.这个效果在单线程的情况不存在.随着线程数量,分配数以及运行时间的增加,出现的概率也在增加.这样,_nalloc起初有足够的空间来适应工作集,然后就出现一些非预期的情况,给出上面的条件则更可能出现这样的效果.


  我认为这是全局块链表的隐含代价.随着运行时间和分配数量的增加,在链表中相邻的块更可能来自不同的arena,每个arena可能已经被强制退出共享的LLC.当它获取这些块的时候,大多数分配强制加载多个高速缓存线到shave.如果malloc返回块处于"arena"无序状态,则free()更可能在这些块调用时处于更糟糕的状态,并在合并时,获取更多的外部高速缓存线.


  这是纯单线程的效果--为什么在更多的线程的时候,情况会变得更糟糕呢?我认为,这是因为更多的线程导致访问超出了更多的arena.单线程程序可以为一个合适大小的块搜索所有的arena.但是在多个线程的情况下的一个线程,必须限制自身在子集之中,这样更可能使用mmap生成新的arena.


  所以假设处于可怜的境地,即便是单线程的情况下,而在多线程未充分利用的情况下,结果会更糟糕.(这并不是我所听到的它使用的碎片--碎片是连续块"存在",但是你不能访问它,因为地址空间是分离的).


  注意:在100%的并行基准测试中,不应该有冲突丢失--在同样的测试中,nalloc的低LLC丢失率反映了这种情况.回想一下,我应该通过某种方式来测试我的假设,而不是跳到一个新的分配器.


  更新:在单线程情况下,我通过增加分配数进行"测试",得到了相同的缺失率.所以,实际上,这意味着我的序列算法先天不足,多线程未充分利用(或者其它属性)的时候,即_nalloc获取LLC的时候,情况更糟糕.


  提到合并,除了全局链表,我找不到其它选择.我考虑过部分取消合并,保持单一的"当前arena"指针来检查,复杂度为O(1);或者,尝试提升链表中块的排序.但是418分配意味着,相比于改变简单的事情,增加复杂性看起来并不能获取益处.


  Alex的报告提到,它没有找到现代的合并访问分配器.我自己研究jemalloc,tcmalloc以及一些无锁malloc也没有任何发现.我觉得,我可能已经发现,为何每个人都避免合并访问了.在给定硬件后,他们一定认为这太幼稚太天真.



酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部