Intel Intrinsics 英特尔指令集简介

指令集的作用

在编写数字图像处理的算法时,为了加快算法的运行速度,我们通常会采取一些方法来优化代码,提高代码运行速度。实现代码的并行运算是其中一种很好的方法。

代码的并行运算大致分为两类并行,指令级并行和数据级并行。数据集并行是在单个指令运算过程中通过同时处理多个数据元素来提高运算效率,这是从数据层面出发的低层次的并行。而指令级并行指的是通过同时执行多个指令处理同一组数据来提高计算效率,这是从指令的角度出发的高层次的并行。

指令集就是实现数据集并行运算的工具。

数据级并行运算的原理

数据级并行运算是通过什么原理实现的加快运算速度?这是使用前指令集首先要思考的问题。下面笔者根据自己的理解抛砖引玉,粗浅地解释一下。

数据级并行简单来说,就是将要运行相同运算的多个数据集合起来,通过一次运算得出结果。形象一点的比喻就是原本我们一次可以握一支笔写一个字,现在我们充分发挥我们手的潜力,一次抓10支笔写10个相同的字,这样就是数据级并行。相应的,指令集并行就是找10个人同时帮我们写字。

现代计算机的cpu基本分为32位和64位型,这意味着它们一次可以运算32位或者64位的数据。但是通过超标量或者超线程技术,cpu现在可以在一个周期内处理128位乃至更多的数据。接下来我们介绍的指令集主要是SSE类型的,因此下文暂且认为cpu在一个时钟周期可以完成128位数据的计算。

假设我们现在需要计算的是“a+b”,并且类似的计算需要重复许多次,“a”和“b”分别是32位int型数据。那么我们需要将“a”和“b”分别存储进计算机的内存中,它们各自占据4字节的存储空间。当运行一次计算时,我们将“a”和“b”读取入cpu,存放在两个128位寄存器中,这一步需要占据两个寄存器。然后将两个寄存器中的“a”和“b”调入ALU中完成加法计算,这需要一个cpu时钟周期。最后将数据从cpu存储进内存。在这个过程中,我们不免发现有一些计算过程出现了严重的浪费:cpu本来在一个时钟周期可以计算128位数据,但是在这里实际只计算了32位有意义的数据,这中间的96位运算空间被无意义的位置填充占据了。如果我们可以将这96位的空间利用起来,岂不是一个时钟周期可以完成4组“a+b”运算,这样可以将运算次数减少3/4,时间也能相应减少。并且再进一步,我们是不是可以将“a”和“b”只用8位数据来表示,一个寄存器可以存储16个数据,那么一个时钟周期可以完成16组“a+b”运算,这样又可以节省很多计算空间,运算效率又可以大幅提高。这就是数据级并行的意义。

SSE类型指令入门

SSE类型的指令集使用的是cpu中的128位寄存器存储数据,这意味着所有的SSE指令集运算数据都是128位的。我们需要做的事就是将多个数据从内存读取入寄存器,然后进行寄存器数据的运算,最后将运算结果从寄存器中存入内存。这其中就需要将数据存入寄存器的指令;进行寄存器运算的特殊运算指令;将寄存器中的数据存入内存的指令。内存中的数据有浮点型,整型等,相应的需要读取入并存放在不同类型的寄存器中:float型寄存器:__m128;double型:__m128d;int型:__m128i。而这些不同的数据类型使得同样的运算对于不同的数据有不同的函数来实现。例如对于将数据从内存存入寄存器的load函数,有如下不同的形式:

__m128d _mm_load_pd (double const* mem_addr);

__m128 _mm_load_ps (float const* mem_addr);

__m128i _mm_load_si128 (__m128i const* mem_addr)

...

因此,在编写指令集运算代码时需要时刻注意当前运算的数据类型是什么,依此来选择不同的运算函数。

了解更多的指令集函数和用法可以访问Intel指令集的官方网站:https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=6475,6470,6532&text=_mm_

指令集运用的难点

指令集虽然提高了运算的并行度,提高了运算的速度,但与之相对的是代码编写的难度提高了。想要将一个个独立的运算聚合起来实现并行运算,其中涉及到许多精妙的数据处理技巧。例如,笔者曾经在实现BGR图像转换到HSV图像的指令集代码编写中就遇到了这样的困难:BGR图像的像素是分为B、G、R三个通道的,而在运算过程中需要将通道中的数据分离,即将不同像素的B通道值提取出来存放在一个寄存器变量中,R、G也做相同操作。想要实现这样的通道分离,如果使用shuffle函数一个个地提取,效率非常低。但是有一种很高效的方法可以通过多次unpack和slli(左移)操作将通道值进行分离,读者可以自己思考一下。

总的来说,Intel指令集提供了一种高效简洁的方法让我们可以轻松地实现数据级并行运算,这对于运算量较大,运算重复度较高的算法,如图像处理算法的优化很有好处。

  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值