你猜 为什么A64为什么没有LDM和STM指令了,而是用LDP跟STP呢?

一、前言

我们知道在Arm Arch32里面有个突发传输指令LDM、STM,也就是说可以一次传输多个值,到底是多少个呢?根据手册里面所说:加载和存储多个寄存器。寄存器r0到r15的任何组合均可在ARM状态下传输。

也就是说传输到通用寄存器里面一次可以传输很多啊!

但是到了Arch64里面就取消掉这个指令了,取而代之的是LDP和STP,固定的一次最多只能取2个值,为何呢?

这篇文章接下来的部分就是为了探究这个问题的!

二、资料搜集

资料:《Cortex_A57_Software_Optimization_Guide_external》
中说到了用LDP做memcopy的好处是可以尽可能地利用load和store的pipeline:


4.5 Load/Store Throughput

The Cortex-A57 processor includes separate load and store pipelines, which allow it to execute one load μop and one store μop every cycle. .

译:由于a57是有分别独立存在的加载、存储流水线,也就是说配合多发射就可能在一个cycle内同时执行两条(ldr、str)指令。

To achieve maximum throughput for memory copy (or similar loops), one should do the following.

实现内存复制最大吞吐的指导思想如下:

  • Unroll the loop to include multiple load and store operations per iteration, minimizing the overheads of looping.(老生常谈:循环展开,使得循环部分产生的过冲减少,其实就是减少循环逻辑部分在整个指令执行数里面的比例,从而提高准确率以及减少分支预测的次数。
  • Use discrete, non-writeback forms of load and store instructions (such as LDRD and STRD), interleaving them so that one load and one store operation may be performed each cycle. Avoid load-/store-multiple instruction encodings (such as LDM and STM), which lead to separated bursts of load and store μops which may not allow concurrent utilization of both the load and store pipelines.

使用离散的、非写回的内存指令,并间隔开来从而最大化利用ld/st的双pipeline特性;避免使用LDM跟STM,因为这样子的话就会产生一些分散的突发传输,从而无法合理利用双pipeline特性。

The following example shows a recommended instruction sequence for a long memory copy in AArch32 state:

Loop_start:
    SUBS r2,r2,#64
    LDRD r3,r4,[r1,#0] 
    STRD r3,r4,[r0,#0] 
    LDRD r3,r4,[r1,#8] 
    STRD r3,r4,[r0,#8] 
    LDRD r3,r4,[r1,#16] 
    STRD r3,r4,[r0,#16] 
    LDRD r3,r4,[r1,#24] 
    STRD r3,r4,[r0,#24] 
    LDRD r3,r4,[r1,#32] 
    STRD r3,r4,[r0,#32] 
    LDRD r3,r4,[r1,#40] 
    STRD r3,r4,[r0,#40] 
    LDRD r3,r4,[r1,#48] 
    STRD r3,r4,[r0,#48] 
    LDRD r3,r4,[r1,#56] 
    STRD r3,r4,[r0,#56] 
    ADD r1,r1,#64
    ADD r0,r0,#64 
    BGT Loop_start

A recommended copy routine for AArch64 would look similar to the sequence above, but would use LDP/STP instructions.

小结:上面的代码就是利用了循环展开、间隔LDRD和STRD从而利用双pipeline实现该两条指令并发执行。最后页也说了下,在Arch64模式下也是类似处理利用LDP/STP指令。


4.7 Non-Temporal Loads/Stores

The ARM v8-A architecture provides load/store non-temporal pair instructions (LDNP/STNP) that provide a hint to the memory system that an access is non-temporal or streaming, and unlikely to be repeated in the near future.

也就是说在ARM v8-A架构里面LDNP/STNP指令是non-temporal的,也就是说当你用这条指令的时候,就会给存储子系统传达这么一个消息:我现在处理的内存数据是流式的、非临时的,在不久的将来也是不会使用的。

Versions of the Cortex-A57 processor prior to r1p3 do not prefetch or cache non-temporal data and hence, there could be a performance degradation when using non-temporal loads/stores instead of normal loads/stores. Ignoring the non-temporal hint will avoid this degradation. To this effect, it is recommended that bit 52 of the CPU auxiliary control register (CPUACTLR_EL1[52]) be always enabled.

从上面的资料我们大概知道用LDP跟STP可以最大化利用ARM v8-A架构的存储双pipeline架构,但是其实里面还有很多细节的信息我们不清楚,因此我们继续进一步深挖:

(我想以后无论我干什么事情,都要是有这种耐心、严谨、深入实践的精神,应该人生是不会太困惑的吧!用心做好每一件事,不忘初心!)

  • non-writeback指令代表什么意思?
  • non-temporal指令代表什么意思?
  • LDP/STP和LDNP/STNP指令的区别及各自特点?

三、思考&继续前行

把握了大的框架思想后,接下来就是填充细节了,不用急,沉下心来,慢慢来!

上面的writeback什么的是cache的一些特性参数,因此我们先看cache部分怎么解释。

这里提前介绍下我们的资料及其特点:

  • 《ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture profile》Printed on: December 19, 2017

    • 这个是Arm Archv8-A profile文档,跟一般芯片数据手册一样介绍寄存器信息的,指令具体怎么用,有什么细节就去这里查了!也就是说是给原厂的底层开发人员看的,或者是驱动开发人员看的,总之很底层了!参考对比当年的单片机开发人员。
  • 《ARM® Cortex®-A Series Version: 1.0 Programmer’s Guide for ARMv8-A》Copyright © 2015 ARM. All rights reserved.

    • 这里讲的很直白了,就是编程手册,给一般程序员看的,里面讲了ARM的一些宏观层面上的模块,也就是粗略介绍了下有哪些模块,有哪些特性,单数具体的参数就没有了!比如指令参数以及指令使用这里就没有了!

3.1 cache

我这里就不从cache的架构一路讲下来了,具体细节参看我以前写的cache专题文章。

先大概讲下哈:
我们写的时候是不是有两种情况,一种是写命中一种是写miss:

  • 写命中:更新cache中的副本后

    • write-through:直接一层一层往底层写回去,这样子回浪费很大的总线带宽啊!
    • write-back: 尽可能地推迟更新,只有当这个cache line被踢除的时候才把它写回到下一层中,注意不是写回最底层哟,而是下一层;这样做的好处是减少总线流量,缺点是这样的操作复杂性就增高了啊!成本高了!
  • 写不命中

    • write-allocate: 读取低一层中的块来更新这个告诉缓存块,注意都是以块也就是cache line为单位哈!
    • non-write-allocate: 避开高速缓存,直接把这个字写入到低一层中。

直写高速缓存 --通常-->非写分配
写回高速缓存 --通常-->写分配

接下来主要就cache的一些策略结合官方文档进行介绍。

  • 《ARM® Cortex®-A Series Version: 1.0 Programmer’s Guide for ARMv8-A》
ARM® Cortex®-A Series Version: 1.0 Programmer’s Guide for ARMv8-A

高速缓存策略使我们能够描述何时应该将一行分配给数据缓存,以及当一个store指令在数据缓存中被执行时,应该发生什么情况。

cache的分配策略如下:

  • 写分配:也就是当你只写1 byte miss的时候,硬件就不管你三七二十一,直接产生一个突发传输给memory子系统,然后获取到一个cache line的数据,cache line全部获取到位之后才把你要的那1 byte数据给你,怎么样是不是听着就很浪费。这就好比在古代:杨贵妃说想要吃荔枝了,这可不得了,一道圣旨发下,底下的百官一阵折腾弄来了一大车的荔枝,但是最后到杨贵妃嘴里的最多就开始的那一盆子吧~你说是不是劳民伤财,浪费资源啊!
  • 读分配:当读miss发生的时候就给其分配一个cache line。

3.2 prefetch

预取就是告诉memory子系统,我有个数据马上要用,你给安排一下!嘿嘿~像不像真实世界的走后门啊!提前打声招呼,提前准备好!VIP通道~~

这里分别介绍了在64bit跟32bit模式下指令的差异,我们主要关注的是预取的策略policy字段:

  • KEEP就是保持在cache内部:又叫temporal prefetch,就是正常的额cache 分配策略;
  • STRM就是流式处理,数据不会存储在cache里面的,也就是从cache上面流过,不留痕迹:non-temporal prefetch也就是说内存数据只用一次的,你不要放到cache 里面来浪费空间了,不要影响我的cache hit rate了。

3.3 LDP/STP

首先告诉你64bit模式下是没有32bit模式下的LDM跟STM指令的:

特点如下:

  • 32bit模式下也是有LDRD跟STD指令的,但是在64bit模式下任意的两个整型寄存器都是可以读或者写的。
  • 数据的读写是内存里面的连续位置的;
  • 地址模式更严格:只能base + offset的模式进行访存,offset范围是正负127范围(7bit);
  • 与32bit的LDRD跟STD指令不同的是:64bit模式下支持非对齐访问。
  • 注意:LDP是支持SIMD的啊!

下面可以看到各种允许的访问方式:


这里对比看一下你就知道上述的两个参考文件的区别,这是profile文件,里面讲了指令具体怎么用的:

3.4 LDNP/STNP

  • LDNP跟STNP是Armv8才有的机制,non-temporal也就是说我读写的时候数据是不会存到cache里面来的!也就是说假如我只要2byte的数据,通常系统会加载1个cache line进来,但是只要用了LDNP这个指令,系统就不会一下加载一整个cache line进来了,而是只加载2byte进来,从而减少总线流量,进而可能减少取数据的时间;因此LDNP这种指令只适合那种数据量比较少的情况(一般小于一个cahche line),避免cache line加载的耗时耗费资源的情况。

  • non-temporal加载和存储能够放松对访存顺序的要求,如下图中的例子,LDNP可能比LDR要提前执行(因为我不需要进行cache line fill操作啊,我是流式读的呀,所以你LDR慢慢去cache line fill吧,我先把媳妇,哦不,数据给先娶回去了!),但是这里这样子就出问题了,因此要加barriar,从而保证执行顺序。

  • 只支持一种访存模式;
  • 这个指令会告诉memory子系统:我这是流式访存,这个数据我暂时只用一次的,因此就不劳烦你把数据给cache 缓存起来了!但是基于memory子系统类型,可能支持读预取和写打包加速等操作!
In addition, there is an exception to the usual memory ordering rules. 
If an address dependency exists between two memory reads, and a Load Non-temporal Pair instruction generated the second read, then in the absence of any other barrier mechanism to achieve order, the memory accesses can be observed in any order by the other observers within the shareability domain of the memory addresses being accessed.

此外,通常的内存排序规则有一个例外。如果两个内存读之间存在地址依赖关系,第二个读指令是LDNP产生的,然后在没有任何其他屏障机制来保证顺序的情况下,这个可能就会乱序执行的!

是不是说可以利用这个来增大吞吐呢?

四、总结

  • 在Arm v8-A架构里面因为有两个分别独立的ld、st pipeline,因此交叉使用LDP、STP指令可以并行使用pipeline,增大吞吐(因为armv7一般是单个加载存储单元,因此LDM、STM更有效);

  • LDNP、STNP是流式处理数据的,不会进行cache line fill操作,因此适合少量数据处理的情形,减少总线流量,比如堆栈恢复的时候,我堆栈就那么几个字节的数据,你常规操作是要加载一个cache line回来的啊,污染cahche空间不说还增大总线流量,因此我用LDNP更有效;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容

  • 目录:1.数据依赖性2.程序顺序规则3.重排序对多线程的影响4.编译器重排序5.指令集并行的重排序6.内存系统的重...
    西部小笼包阅读 16,342评论 9 25
  • 在今天,我看了驯龙高手。因为我决定看一部电影,然后把电影的情节写到文章上。我爸给我选了驯龙高手,所以我就看驯龙高手...
    肖子岩阅读 603评论 4 0
  • 没有多进程,即使CPU有多个核心,程序只是运行在一个核心上,无法利用多进程提升效率。5000万次加法,如果需要2....
    凯茜的老爸阅读 871评论 1 2
  • http://blog.cocoachina.com/article/61433
    TsingQue阅读 275评论 0 0
  • 我是一名职场菜鸟,甚至可以说是一个十足的傻小白。 即将毕业,却也有各种惆怅:不知道现在的选择是否正确,更不知道是否...
    笨笨一直在努力阅读 172评论 0 0