《Analysis and Optimization of the Memory Hierarchy for Graph Processing Workloads》【第一部分阅读笔记】

Analysis and Optimization of the Memory Hierarchy for Graph Processing Workloads

《Analysis and Optimization of the Memory Hierarchy for Graph Processing Workloads》

Basak A, Li S, Hu X, et al. Analysis and optimization of the memory hierarchy for graph processing workloads[C]//2019 IEEE International Symposium on High Performance Computer Architecture (HPCA). IEEE, 2019: 373-386.

主要内容:以体系结构的视角,对图数据处理过程中的存储层次(memory hierarchy)进行「分析」和「优化」,本次关注的重点是「分析」部分。


Abstract

本文的贡献:在单机内存图分析(single-machine in-memory graph analytics)的情况下,分析和优化图处理的存储层次。

  1. 分析:乱序(OoO)核中的存储级并行(MLP)+ cache层面的请求重用距离(reuse distance)。
  2. 优化:提出了DROPLET预取(prefetch)架构(略)。

I. INTRODUCTION

【单机内存CPU平台】 VS 【分布式系统、核外系统、专用加速器】
鉴于其诸多的优点,本文使用使用的是单机内存CPU平台。

  • 避免网络通信
  • 减少编程量
  • 避免预处理

但是,它也有缺点——存储子系统效率低下,45%的周期都会因为要从DRAM中取数据(L1、L2、L3 cache都不命中)而导致内核的停顿(stall)。

在这里插入图片描述

为了解决这个问题,本文分为2个阶段:分析+优化。
分析阶段的重要发现:

  1. (不同数据类型)load指令之间的依赖链(load-load dependency chain)是实现高MLP的主要瓶颈。
  2. 不同数据类型之间存在着不同的重用距离(heterogeneous reuse distance),这会导致不同级别的cache对不同类型的数据有着不同的影响。

优化阶段(略)。

II. BACKGROUND

一些概念的介绍。

A. Graph Data Types and Data Layout

图数据的存储布局(layout):CSR存储方式。并且可以将其划分为3种数据类型:

  • Structure data(结构数据): the neighbor ID array(邻居ID数组)
  • Property data(属性数据): the vertex data array(节点属性数组)
  • Intermediate data: any other data.

其中结构和属性数据比较重要,在后面的分析中经常出现。

在这里插入图片描述

B. Latency Tolerance in Modem CPUs

现代CPU的3种延迟容忍技术(latency tolerance technology):

  1. 由乱序执行所产生的MLP
  2. cache技术
  3. 硬件预取

III. EXPERIMENT SETUP

实验的仿真平台(baseline的体系结构)和benchmark(算法和数据集)的介绍。

IV. CHARACTERIZATION

分别从内核和cache层面进行分析,有6个observation,是很重要的一部分!!!

A. Analysis of the Core and the MLP

Observation#1:

指令窗口大小(ROB等)不是影响MLP的因素。
类比多体交叉存储器,我们可以大胆地猜测MLP到底是怎么回事——当流水线上乱序执行的指令之间所需要的数据相互独立、没有依赖关系,我们就可以在一个周期内并行的从存储器中读取多条数据,这样其实就实现了MLP。
一般来说,指令窗口越大,那么可开发的MLP就会越多,并行性就会越好。但是实验发现在图数据处理方面并不是这样的,增大ROB,带宽和加速比的提升都很小。
出现这种情况的原因在Observation#2中给出了——指令之间的数据依赖性。

Observation#2:

load指令之间的依赖链阻止了高MLP的实现。
这种依赖关系和数据相关中的RAW(写后读相关)的思路比较像。RAW是必须等待前面的指令写入,后面的指令才能够从内存中load取出正确的数据,否则就要一直停顿等待。而本文所说的load-load dependency chain其实就是,consumer load指令所需要访存的地址必须要等producer load指令执行完才能够得到。此外,这种依赖链比较短,consumer开始执行的时候producer大概率没执行完,所以consumer需要等待producer完成,这就导致了两条指令之间的依赖关系。
这种依赖关系使得两条指令不能够并行执行,导致了流水线的断流和低MLP。
对应于图数据的解释在Observation#3中给出。

Observation#3:

在依赖链中,图属性数据是消费者(consumer),图结构数据是生产者(producer)。
为什么是这个结果?
其实不难发现,以CSR存储方式为例,图算法中最频繁的操作之一就是「取出邻居节点的属性」。这个操作分为2步:

  1. 通过structure data,找到邻居节点ID。–>producer load
  2. 用邻居ID(相当于address)进行偏移寻址,找到其property data。–>consumer load

可以发现第2步的地址需要第1步的结果,这就构成了依赖关系。
我认为,出现这种情况的原因主要还是在图数据本身的抽象存储结构上——不论是CSR形式还是邻接矩阵形式,图数据的「结构信息」和「属性信息」都是分开存储的。也就是说,结构信息中存储邻居ID,而属性信息又单独由ID进行索引(属性信息通过结构信息间接地索引)。这样,取出邻居节点的属性就需要具有依赖关系的2步,也就导致了load-load dependency chain。

B. Analysis of the Cache Hierarchy

Observation#4:

私有L2 cache的影响可忽略,共享L3 cache具有高敏感度。
增大L3 cache容量–>「cache不命中率降低,但是访存延迟增大」–>整体时间大幅减少,加速比可观。
可以没有L2 cache,影响不大。
具体原因在Observation#6中给出。

Observation#5:

属性数据是增大L3 cache容量的主要受益者,结构数据基本不受影响。
增大L3 cache容量,属性数据的片外(DRAM)访问次数减少的最多。
具体原因在Observation#6中给出。

Observation#6:

图结构数据的重用距离最长,图属性数据的重用距离要比被L2 cache服务的数据的重用距离长。

结构数据的重用距离到DRAM,因此L3 cache对其基本没有影响:

  • L1 cache命中
  • L2 cache命中
  • L3 cache命中
  • DRAM

属性数据的重用距离到L3 cache,因此L2 cache对其基本没有影响:

  • L1 cache命中
  • L2 cache命中
  • L3 cache命中
  • DRAM

以结构数据为例,当L1 cache不命中时,这些数据已经很久没有被访问过了,以至于需要去DRAM去找。属性数据同理,也有同样的现象。这也就导致了L2 cache甚至是L3 cache都派不上用场。
我认为,出现这种情况的原因主要是图数据本身的特征——重尾性(heavy tailed)和幂律度分布。从实验结果可以看到,L1 cache的命中率已经比较可观了,这说明图数据的局部性还是可以的,并没有想象中的那么糟。那为什么还会出现如此长的重用距离呢?这是因为,由于幂律度分布,存在着少量的“明星节点”,这些节点被频繁地访问,但是它们的邻居大部分都是一些“小透明”,这些节点最不经常被访问。
这样,我们再去解释实验现象:以结构数据为例,最经常访问的“明星节点”被放到L1 cache中,这样就有了较好的局部性;最不经常访问的“小透明”节点在被用到一次之后,长时间都“无人问津”,很快就被淘汰出了L3 cache,下次再用的时候只能够千里迢迢地从DRAM中取出了。
重尾性和幂律度分布正好反映出了图数据这种极端的特性。

C. Summary and Opportunities

这一部分主要讨论的两个问题是:

  1. 不同数据类型具有不同的重用距离,并且导致了密集的DRAM访问。
  2. 由于load指令依赖关系所导致的低MLP,限制了DRAM访问的重叠(并行)执行。

解决这两个问题所采取的策略:预取(prefetch)。具体的策略见表5。

在这里插入图片描述

之后的内容略。

猜你喜欢

转载自blog.csdn.net/weixin_41650348/article/details/112561644
今日推荐