矩阵转置的SSE汇编优化艺术以及ARM cortext 汇编优化

原创 2012年12月27日 09:19:45

 

平时我们做图像处理或者视频处理, 很多地方会用到矩阵转置:

比如: DCT变换, 图像旋转, 图像滤波, 以及一些数据的内存行和列的交换等, 会大量使用转置这个动作.

然而由于数据量很大,处理速度很慢!如何来提高处理速度呢?

下面看看分析: 

HEVC中有个地方是如下这样实现(直接行和列对应的位置交换):

      Pel  tmp;
      for (k=0;k<blkSize-1;k++)
      {
        for (l=k+1;l<blkSize;l++)
        {
          tmp                 = pDst[k*dstStride+l];
          pDst[k*dstStride+l] = pDst[l*dstStride+k];
          pDst[l*dstStride+k] = tmp;
        }
      }


 

如何用汇编来实现呢?

我们先用SSE汇编来实现一个8X8的矩阵转置吧: 这里输入地址pSrc_128[i] 和输出地址pDst_128[i]可以相同也可以不同:

相同的话就是原地转置, 不同的话就是非原地转置.

  __m128i* m_pSrc_tmp = pSrc_128[i];
  __m128i* m_pDst_tmp = pDst_128[i];
  __m128i Org_8_0,Org_8_1, Org_8_2, Org_8_3;
  __m128i tttt1,tttt2,tttt3,tttt4,tttt33,tttt44;
  __m128i tttt5,tttt6, tttt7, tttt8;
  int stride_ii = dstStride>>3;
//one
  Org_8_0 = _mm_load_si128(m_pSrc_tmp);
  m_pSrc_tmp+=8;
  Org_8_1 = _mm_load_si128(m_pSrc_tmp);
  m_pSrc_tmp+=8;
  Org_8_2 = _mm_load_si128(m_pSrc_tmp);
  m_pSrc_tmp+=8;
  Org_8_3 = _mm_load_si128(m_pSrc_tmp);
  m_pSrc_tmp+=8;

  tttt1 = _mm_unpacklo_epi16(Org_8_0, Org_8_1);
  tttt2 = _mm_unpacklo_epi16(Org_8_2, Org_8_3);
  tttt3 = _mm_unpackhi_epi16(Org_8_0, Org_8_1);
  tttt4 = _mm_unpackhi_epi16(Org_8_2, Org_8_3);

  tttt5 = _mm_unpacklo_epi32(tttt1, tttt2);
  tttt6 = _mm_unpackhi_epi32(tttt1, tttt2);

  Org_8_0 = _mm_load_si128(m_pSrc_tmp);
  m_pSrc_tmp+=8;; 
  Org_8_1 = _mm_load_si128(m_pSrc_tmp);
  m_pSrc_tmp+=8;
  Org_8_2 = _mm_load_si128(m_pSrc_tmp);
  m_pSrc_tmp+=8; 
  Org_8_3 = _mm_load_si128(m_pSrc_tmp);
  //m_pSrc_tmp+=8;

  tttt1 = _mm_unpacklo_epi16(Org_8_0, Org_8_1);
  tttt2 = _mm_unpacklo_epi16(Org_8_2, Org_8_3);
  tttt33 = _mm_unpackhi_epi16(Org_8_0, Org_8_1);
  tttt44 = _mm_unpackhi_epi16(Org_8_2, Org_8_3);

  tttt7 = _mm_unpacklo_epi32(tttt1, tttt2);
  tttt8 = _mm_unpackhi_epi32(tttt1, tttt2);

  tttt1 = _mm_unpacklo_epi64(tttt5, tttt7);
  tttt2 = _mm_unpackhi_epi64(tttt5, tttt7);
  _mm_storeu_si128(m_pDst_tmp, tttt1);
  m_pDst_tmp+=stride_ii;
  _mm_storeu_si128(m_pDst_tmp, tttt2);
  m_pDst_tmp+=stride_ii;
  tttt5 = _mm_unpacklo_epi64(tttt6, tttt8);
  tttt7 = _mm_unpackhi_epi64(tttt6, tttt8);
  _mm_storeu_si128(m_pDst_tmp, tttt5);
  m_pDst_tmp+=stride_ii;
  _mm_storeu_si128(m_pDst_tmp, tttt7);
  m_pDst_tmp+=stride_ii;

//tow
  tttt5 = _mm_unpacklo_epi32(tttt3, tttt4);
  tttt6 = _mm_unpackhi_epi32(tttt3, tttt4);

  tttt7 = _mm_unpacklo_epi32(tttt33, tttt44);
  tttt8 = _mm_unpackhi_epi32(tttt33, tttt44);

  tttt1 = _mm_unpacklo_epi64(tttt5, tttt7);
  tttt2 = _mm_unpackhi_epi64(tttt5, tttt7);
  _mm_storeu_si128(m_pDst_tmp, tttt1);
  m_pDst_tmp+=stride_ii;
  _mm_storeu_si128(m_pDst_tmp, tttt2);
  m_pDst_tmp+=stride_ii;
  tttt5 = _mm_unpacklo_epi64(tttt6, tttt8);
  tttt7 = _mm_unpackhi_epi64(tttt6, tttt8);
  _mm_storeu_si128(m_pDst_tmp, tttt5);
  m_pDst_tmp+=stride_ii;
  _mm_storeu_si128(m_pDst_tmp, tttt7);


要实现的是NXN的转置,如何实现呢:

基于8X8来实现NXN的块或者图像的转置:

这里先把NXN划分为size_case 个8X8, 然后循环调用8X8的转置!

 

  __m128i* pDst_128[64];
  __m128i* pSrc_128[64];
  int size_case = (blkSize>>3);
  dstStride = dstStride_tmp;
  for(int y = 0; y<size_case; y++)//对所有8x8的块进行地址映射
   for(int x = 0; x<size_case; x++)
   {
    pSrc_128[y*size_case + x] = (__m128i*)(pDst + 8*x + y*8*64);
    pDst_128[y*size_case + x] = (__m128i*)(rpDst + 8*y + x*8*dstStride);
   }

  size_case = size_case*size_case;
  for(int  i = 0;i <size_case; i++)//开始转置
  {

     8x8转置的代码:

 }

通过比较, 用SSE汇编优化实现转置比用纯 C代码实现的转置速度快5倍左右! 

 

同样在ARM cortext上的汇编优化也是基于这个原理:

主要循环体代码如下:

	VTRN.16 q8, q9
	VTRN.16 q10, q11
	VTRN.16 q4, q5
	VTRN.16 q6, q7
	VTRN.32 q8, q10
	VTRN.32 q9, q11
	VTRN.32 q4, q6
	VTRN.32 q5, q7
	VSWP d17, d8
	VSWP d19, d10
	VSWP d21, d12
	VSWP d23, d14	


感兴趣的可以自己调试下!

 

当然DSP上也是同样的方法, 只是涉及到的指令不同而已!

 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

sse转neon

sse转neon

ARM NEON 指令

在初学NDK时,接触到 HelloNeon例程,了解到 Neon是ARMv7-AR 系列中引入的并行模块,可以让你同时操作8个16位数据或4个32位数据,在信号处理,图像处理,视频编解码优化方面有很高...

SSE指令的使用学习

1. 什么是指令集? 指令集是为了增强CPU在某些方面(如多媒体)的功能而特意开发出的一组程序代码集合。 2.常见的指令集有哪些呢? 1)MMX(Multi-Media Extensions,做媒体扩...

SSE指令集入门

Intel公司的单指令多数据流式扩展(SSE,Streaming SIMD Extensions)技术能够有效增强CPU浮点运算的能力。Visual Studio .NET 2003提供了对SSE指令...

CUDA之矩阵转置程序优化实例

Catalog 已经达到极限了?影响代码性能的两个主要方面优化代码内存操作 看代码内存操作是否有效——DRAM utilizationcoalesce合并从little’s Law中找继续...

c++类模板及参数类型的运行时判断

/* C++类模板及参数类型的运行时判断(typeid) */ #include #include #include using namespace std; template class...

sse优化一例

sse优化一例

矩阵转置的SSE汇编优化艺术以及ARM cortext 汇编优化

转至http://blog.csdn.net/feixiang_john/article/details/8438658 平时我们做图像处理或者视频处理, 很多地方会用到矩阵转置: 比...

矩阵转置的SSE汇编优化艺术以及ARM cortext 汇编优化 .

原文地址:http://blog.csdn.net/feixiang_john/article/details/8438658 平时我们做图像处理或者视频处理, 很多地方会用到矩阵转置: 比如: ...

使用MMX/SSE汇编指令集优化视频开发

1、汇编指令集 目前大部分的PC机采用的都是Intel或者AMD的CPU,其支持的多媒体汇编指令有: MMX:多媒体扩展指令(MultiMedia eXtention),该指令由Intel在1996年...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:矩阵转置的SSE汇编优化艺术以及ARM cortext 汇编优化
举报原因:
原因补充:

(最多只允许输入30个字)