精华内容
下载资源
问答
  • 2016-10-29 23:21:14
    #include <stdio.h>
    #include <time.h>
    #define N 4


    int main()
    {
        int arr[N][N];
    int i = 0;
    int j = 0;
    int temp = 0;
    srand (time(NULL));
    for ( i = 0 ; i < N ; i++)
    {
    for ( j = 0 ; j < N ; j++)
    {


    arr[i][j] = rand()%100;
    }
    }
    for( i = 0 ; i < N ; i++)
    {
    for ( j = 0 ; j < N ; j++)
    {
    printf("%3d",arr[i][j]);

    if ( j+1 == N)
    {
    printf("\n");
    }
        }
    }
    printf("\n");
    i = 0;
    j = 0;

        for ( i = 0 ; i < N ; i++)
    {
    for ( j = i ; j < N ; j++)
    {
    temp = arr[i][j];
    arr[i][j] = arr [j][i];
    arr[j][i] = temp;
    }
    }


    for ( i = 0 ; i < N ; i++)
    {
    for ( j = 0 ; j < N ; j++)
    {
    printf("%3d",arr[i][j]);
    if( j + 1 == N)
    {
    printf("\n");
    }
    }
    }
        return 0;
    }
    更多相关内容
  • ARM汇编实现矩阵转置

    2020-12-16 19:28:49
    基于ARM汇编矩阵转置代码,包含运行实例以及仿真结果,方便初学者更加深入理解ARM汇编语言的语言逻辑
  • 汇编实现矩阵转置

    2020-11-29 22:56:55
    汇编实现矩阵转置 题意: 给定一个 4 * 5 的矩阵 , 把它转置后存到 data2. 思路: 首先汇编不向其他语言,可以直接根据下表访问地址,数组中的数是放在一段连续的内存单元中。也就是说我们转置后还是相当于储存...

    汇编实现矩阵的转置

    题意:
    给定一个 4 * 5 的矩阵 , 把它转置后存到 data2.

    思路:

    1. 首先汇编不向其他语言,可以直接根据下表访问地址,数组中的数是放在一段连续的内存单元中。也就是说我们转置后还是相当于储存在一个一位数组中。
    2. 所以我们可以先模拟一下转置的过程,我们要首先把第一列存入data2 ,再把第二列依次存入 data2…,知道最后一列存入。先考虑第一列如何放入,首先把第一个元素的地址存入寄存器,然后每次 + 4,把这个值存入 data2,同时 data2 的寄存器 ++ ,就可以实现这个功能。那么第二列我们怎么让寄存器回到 第二个元素呢?这里我们可以再用一个寄存器保存上一次是从哪个开始的,每次大循环把这个地址 + 1 就好了。
    3. 我们也可以不用地址寄存器,直接用一个 bx 计数器,记录这一次应该从第几个元素开始 lea si,[data1 + bx] ;每次移动的初始位置,一开始用的 si + bh ,然后发现不行,然后老师说要 16位匹配,所以要用 bx.
    4. 一开始要写二重循环不知道何从下手,以为只能用 cx 作循环记录,其实随便用哪个都行,只要最后判断一下再跳回开头就好了。

    代码:

    DATAs SEGMENT
         N DW 5;
         M DW 4
         DATA1 DB 1,2,3,4
               DB 10,20,30,40
               DB 11,12,13,14
               DB 20,30,40,50
               DB 21,22,23,24
               
         DATA2 DB 20 DUP(0)
    DATAs ends			
    CODES  SEGMENT
         ASSUME    CS:CODES,DS:DATAS
    START:
         mov ax,datas
         mov ds,ax
         lea di,data2
         lea bp,data1
         mov cx,M
         mov dh,0
         
    loop1: 
    	mov si,bp      ;每次移动的初始位置
    	mov bh ,N      ;每次循环次数
    	
        loop2:
          mov dh,[si] 
          mov [di],dh ;移到 data2
          inc di      
          add si,M    ;移到下一行
          dec bh      
          cmp bh,0
    	ja  loop2    
    	
        inc bp        ; 初始位置 ++
    	   
    loop  loop1
     
         MOV  AH,4CH
         INT  21H
    CODES  ENDS
        END   START
    
    
    
    
    
    

    或者:

    DATAs SEGMENT
         N DW 5;
         M DW 4
         DATA1 DB 1,2,3,4
               DB 10,20,30,40
               DB 11,12,13,14
               DB 20,30,40,50
               DB 21,22,23,24
               
         DATA2 DB 20 DUP(0)
    DATAs ends			
    CODES  SEGMENT
         ASSUME    CS:CODES,DS:DATAS
    START:
         mov ax,datas
         mov ds,ax
         lea di,data2
         mov cx,4
         mov bx,0
         
    loop1: 
    	lea si,[data1 + bx]      ;每次移动的初始位置
    	mov dl ,5                ;每次循环次数
    	
        loop2:
    	   mov dh,[si] 
    	   mov [di],dh ;移到 data2
    	   inc di      
    	   add si,M    ;移到下一行
    	   dec dl      
    	   cmp dl,0
    	ja  loop2
    	inc bx        ; 初始位置 ++
    	   
     loop  loop1
     
         MOV  AH,4CH
         INT  21H
    CODES  ENDS
        END   START
    
    
    
    展开全文
  • 平时我们做图像处理或者视频处理, 很多地方会用到矩阵转置: 比如: DCT变换, 图像旋转, 图像滤波, 以及一些数据的内存行和列的交换等, 会大量使用转置这个动作. 然而由于数据量很大,处理速度很慢!如何来提高...

    转至http://blog.csdn.net/feixiang_john/article/details/8438658

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

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

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

    下面看看分析: 

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

    1. Pel  tmp;  
    2. for (k=0;k<blkSize-1;k++)  
    3. {  
    4.   for (l=k+1;l<blkSize;l++)  
    5.   {  
    6.     tmp                 = pDst[k*dstStride+l];  
    7.     pDst[k*dstStride+l] = pDst[l*dstStride+k];  
    8.     pDst[l*dstStride+k] = tmp;  
    9.   }  
    10. }  


     

    如何用汇编来实现呢?

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

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

    1.   __m128i* m_pSrc_tmp = pSrc_128[i];  
    2.   __m128i* m_pDst_tmp = pDst_128[i];  
    3.   __m128i Org_8_0,Org_8_1, Org_8_2, Org_8_3;  
    4.   __m128i tttt1,tttt2,tttt3,tttt4,tttt33,tttt44;  
    5.   __m128i tttt5,tttt6, tttt7, tttt8;  
    6.   int stride_ii = dstStride>>3;  
    7. //one  
    8.   Org_8_0 = _mm_load_si128(m_pSrc_tmp);  
    9.   m_pSrc_tmp+=8;  
    10.   Org_8_1 = _mm_load_si128(m_pSrc_tmp);  
    11.   m_pSrc_tmp+=8;  
    12.   Org_8_2 = _mm_load_si128(m_pSrc_tmp);  
    13.   m_pSrc_tmp+=8;  
    14.   Org_8_3 = _mm_load_si128(m_pSrc_tmp);  
    15.   m_pSrc_tmp+=8;  
    16.   
    17.   tttt1 = _mm_unpacklo_epi16(Org_8_0, Org_8_1);  
    18.   tttt2 = _mm_unpacklo_epi16(Org_8_2, Org_8_3);  
    19.   tttt3 = _mm_unpackhi_epi16(Org_8_0, Org_8_1);  
    20.   tttt4 = _mm_unpackhi_epi16(Org_8_2, Org_8_3);  
    21.   
    22.   tttt5 = _mm_unpacklo_epi32(tttt1, tttt2);  
    23.   tttt6 = _mm_unpackhi_epi32(tttt1, tttt2);  
    24.   
    25.   Org_8_0 = _mm_load_si128(m_pSrc_tmp);  
    26.   m_pSrc_tmp+=8;;   
    27.   Org_8_1 = _mm_load_si128(m_pSrc_tmp);  
    28.   m_pSrc_tmp+=8;  
    29.   Org_8_2 = _mm_load_si128(m_pSrc_tmp);  
    30.   m_pSrc_tmp+=8;   
    31.   Org_8_3 = _mm_load_si128(m_pSrc_tmp);  
    32.   //m_pSrc_tmp+=8;  
    33.   
    34.   tttt1 = _mm_unpacklo_epi16(Org_8_0, Org_8_1);  
    35.   tttt2 = _mm_unpacklo_epi16(Org_8_2, Org_8_3);  
    36.   tttt33 = _mm_unpackhi_epi16(Org_8_0, Org_8_1);  
    37.   tttt44 = _mm_unpackhi_epi16(Org_8_2, Org_8_3);  
    38.   
    39.   tttt7 = _mm_unpacklo_epi32(tttt1, tttt2);  
    40.   tttt8 = _mm_unpackhi_epi32(tttt1, tttt2);  
    41.   
    42.   tttt1 = _mm_unpacklo_epi64(tttt5, tttt7);  
    43.   tttt2 = _mm_unpackhi_epi64(tttt5, tttt7);  
    44.   _mm_storeu_si128(m_pDst_tmp, tttt1);  
    45.   m_pDst_tmp+=stride_ii;  
    46.   _mm_storeu_si128(m_pDst_tmp, tttt2);  
    47.   m_pDst_tmp+=stride_ii;  
    48.   tttt5 = _mm_unpacklo_epi64(tttt6, tttt8);  
    49.   tttt7 = _mm_unpackhi_epi64(tttt6, tttt8);  
    50.   _mm_storeu_si128(m_pDst_tmp, tttt5);  
    51.   m_pDst_tmp+=stride_ii;  
    52.   _mm_storeu_si128(m_pDst_tmp, tttt7);  
    53.   m_pDst_tmp+=stride_ii;  
    54.   
    55. //tow  
    56.   tttt5 = _mm_unpacklo_epi32(tttt3, tttt4);  
    57.   tttt6 = _mm_unpackhi_epi32(tttt3, tttt4);  
    58.   
    59.   tttt7 = _mm_unpacklo_epi32(tttt33, tttt44);  
    60.   tttt8 = _mm_unpackhi_epi32(tttt33, tttt44);  
    61.   
    62.   tttt1 = _mm_unpacklo_epi64(tttt5, tttt7);  
    63.   tttt2 = _mm_unpackhi_epi64(tttt5, tttt7);  
    64.   _mm_storeu_si128(m_pDst_tmp, tttt1);  
    65.   m_pDst_tmp+=stride_ii;  
    66.   _mm_storeu_si128(m_pDst_tmp, tttt2);  
    67.   m_pDst_tmp+=stride_ii;  
    68.   tttt5 = _mm_unpacklo_epi64(tttt6, tttt8);  
    69.   tttt7 = _mm_unpackhi_epi64(tttt6, tttt8);  
    70.   _mm_storeu_si128(m_pDst_tmp, tttt5);  
    71.   m_pDst_tmp+=stride_ii;  
    72.   _mm_storeu_si128(m_pDst_tmp, tttt7);  


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

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

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

     

    1.  __m128i* pDst_128[64];  
    2.  __m128i* pSrc_128[64];  
    3.  int size_case = (blkSize>>3);  
    4.  dstStride = dstStride_tmp;  
    5.  for(int y = 0; y<size_case; y++)//对所有8x8的块进行地址映射  
    6.   for(int x = 0; x<size_case; x++)  
    7.   {  
    8.    pSrc_128[y*size_case + x] = (__m128i*)(pDst + 8*x + y*8*64);  
    9.    pDst_128[y*size_case + x] = (__m128i*)(rpDst + 8*y + x*8*dstStride);  
    10.   }  
    11.   
    12.  size_case = size_case*size_case;  
    13.  for(int  i = 0;i <size_case; i++)//开始转置  
    14.  {  
    15.   
    16.     8x8转置的代码:  
    17.   
    18. }  

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

     

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

    主要循环体代码如下:

    1. VTRN.16 q8, q9  
    2. VTRN.16 q10, q11  
    3. VTRN.16 q4, q5  
    4. VTRN.16 q6, q7  
    5. VTRN.32 q8, q10  
    6. VTRN.32 q9, q11  
    7. VTRN.32 q4, q6  
    8. VTRN.32 q5, q7  
    9. VSWP d17, d8  
    10. VSWP d19, d10  
    11. VSWP d21, d12  
    12. VSWP d23, d14     


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

     

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

     

    展开全文
  • 平时我们做图像处理或者视频处理, 很多地方会用到矩阵转置: 比如: DCT变换, 图像旋转, 图像滤波, 以及一些数据的内存行和列的交换等, 会大量使用转置这个动作. 然而由于数据量很大,处理速度很慢!如何来提高处理...

    原文地址:http://blog.csdn.net/feixiang_john/article/details/8438658

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

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

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

    下面看看分析: 

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

    1. Pel  tmp;  
    2. for (k=0;k<blkSize-1;k++)  
    3. {  
    4.   for (l=k+1;l<blkSize;l++)  
    5.   {  
    6.     tmp                 = pDst[k*dstStride+l];  
    7.     pDst[k*dstStride+l] = pDst[l*dstStride+k];  
    8.     pDst[l*dstStride+k] = tmp;  
    9.   }  
    10. }  
          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]可以相同也可以不同:

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

    1.   __m128i* m_pSrc_tmp = pSrc_128[i];  
    2.   __m128i* m_pDst_tmp = pDst_128[i];  
    3.   __m128i Org_8_0,Org_8_1, Org_8_2, Org_8_3;  
    4.   __m128i tttt1,tttt2,tttt3,tttt4,tttt33,tttt44;  
    5.   __m128i tttt5,tttt6, tttt7, tttt8;  
    6.   int stride_ii = dstStride>>3;  
    7. //one   
    8.   Org_8_0 = _mm_load_si128(m_pSrc_tmp);  
    9.   m_pSrc_tmp+=8;  
    10.   Org_8_1 = _mm_load_si128(m_pSrc_tmp);  
    11.   m_pSrc_tmp+=8;  
    12.   Org_8_2 = _mm_load_si128(m_pSrc_tmp);  
    13.   m_pSrc_tmp+=8;  
    14.   Org_8_3 = _mm_load_si128(m_pSrc_tmp);  
    15.   m_pSrc_tmp+=8;  
    16.   
    17.   tttt1 = _mm_unpacklo_epi16(Org_8_0, Org_8_1);  
    18.   tttt2 = _mm_unpacklo_epi16(Org_8_2, Org_8_3);  
    19.   tttt3 = _mm_unpackhi_epi16(Org_8_0, Org_8_1);  
    20.   tttt4 = _mm_unpackhi_epi16(Org_8_2, Org_8_3);  
    21.   
    22.   tttt5 = _mm_unpacklo_epi32(tttt1, tttt2);  
    23.   tttt6 = _mm_unpackhi_epi32(tttt1, tttt2);  
    24.   
    25.   Org_8_0 = _mm_load_si128(m_pSrc_tmp);  
    26.   m_pSrc_tmp+=8;;   
    27.   Org_8_1 = _mm_load_si128(m_pSrc_tmp);  
    28.   m_pSrc_tmp+=8;  
    29.   Org_8_2 = _mm_load_si128(m_pSrc_tmp);  
    30.   m_pSrc_tmp+=8;   
    31.   Org_8_3 = _mm_load_si128(m_pSrc_tmp);  
    32.   //m_pSrc_tmp+=8;   
    33.   
    34.   tttt1 = _mm_unpacklo_epi16(Org_8_0, Org_8_1);  
    35.   tttt2 = _mm_unpacklo_epi16(Org_8_2, Org_8_3);  
    36.   tttt33 = _mm_unpackhi_epi16(Org_8_0, Org_8_1);  
    37.   tttt44 = _mm_unpackhi_epi16(Org_8_2, Org_8_3);  
    38.   
    39.   tttt7 = _mm_unpacklo_epi32(tttt1, tttt2);  
    40.   tttt8 = _mm_unpackhi_epi32(tttt1, tttt2);  
    41.   
    42.   tttt1 = _mm_unpacklo_epi64(tttt5, tttt7);  
    43.   tttt2 = _mm_unpackhi_epi64(tttt5, tttt7);  
    44.   _mm_storeu_si128(m_pDst_tmp, tttt1);  
    45.   m_pDst_tmp+=stride_ii;  
    46.   _mm_storeu_si128(m_pDst_tmp, tttt2);  
    47.   m_pDst_tmp+=stride_ii;  
    48.   tttt5 = _mm_unpacklo_epi64(tttt6, tttt8);  
    49.   tttt7 = _mm_unpackhi_epi64(tttt6, tttt8);  
    50.   _mm_storeu_si128(m_pDst_tmp, tttt5);  
    51.   m_pDst_tmp+=stride_ii;  
    52.   _mm_storeu_si128(m_pDst_tmp, tttt7);  
    53.   m_pDst_tmp+=stride_ii;  
    54.   
    55. //tow   
    56.   tttt5 = _mm_unpacklo_epi32(tttt3, tttt4);  
    57.   tttt6 = _mm_unpackhi_epi32(tttt3, tttt4);  
    58.   
    59.   tttt7 = _mm_unpacklo_epi32(tttt33, tttt44);  
    60.   tttt8 = _mm_unpackhi_epi32(tttt33, tttt44);  
    61.   
    62.   tttt1 = _mm_unpacklo_epi64(tttt5, tttt7);  
    63.   tttt2 = _mm_unpackhi_epi64(tttt5, tttt7);  
    64.   _mm_storeu_si128(m_pDst_tmp, tttt1);  
    65.   m_pDst_tmp+=stride_ii;  
    66.   _mm_storeu_si128(m_pDst_tmp, tttt2);  
    67.   m_pDst_tmp+=stride_ii;  
    68.   tttt5 = _mm_unpacklo_epi64(tttt6, tttt8);  
    69.   tttt7 = _mm_unpackhi_epi64(tttt6, tttt8);  
    70.   _mm_storeu_si128(m_pDst_tmp, tttt5);  
    71.   m_pDst_tmp+=stride_ii;  
    72.   _mm_storeu_si128(m_pDst_tmp, tttt7);  
      __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的转置!

     

    1.  __m128i* pDst_128[64];  
    2.  __m128i* pSrc_128[64];  
    3.  int size_case = (blkSize>>3);  
    4.  dstStride = dstStride_tmp;  
    5.  for(int y = 0; y<size_case; y++)//对所有8x8的块进行地址映射   
    6.   for(int x = 0; x<size_case; x++)  
    7.   {  
    8.    pSrc_128[y*size_case + x] = (__m128i*)(pDst + 8*x + y*8*64);  
    9.    pDst_128[y*size_case + x] = (__m128i*)(rpDst + 8*y + x*8*dstStride);  
    10.   }  
    11.   
    12.  size_case = size_case*size_case;  
    13.  for(int  i = 0;i <size_case; i++)//开始转置   
    14.  {  
    15.   
    16.     8x8转置的代码:  
    17.   
    18. }  
      __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上的汇编优化也是基于这个原理:

    主要循环体代码如下:

    1. VTRN.16 q8, q9  
    2. VTRN.16 q10, q11  
    3. VTRN.16 q4, q5  
    4. VTRN.16 q6, q7  
    5. VTRN.32 q8, q10  
    6. VTRN.32 q9, q11  
    7. VTRN.32 q4, q6  
    8. VTRN.32 q5, q7  
    9. VSWP d17, d8  
    10. VSWP d19, d10  
    11. VSWP d21, d12  
    12. VSWP d23, d14     
    	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上也是同样的方法, 只是涉及到的指令不同而已!

     

    展开全文
  • 经历了N天几近抓狂的调试,终于做出了结果。在这里非常非常之感谢帮助我的Tom同学,没有他的耐心帮助,...算法的具体流程是这样的:对于给定的N*N规模的矩阵A,应用下列公式求系数矩阵B//求系数矩阵for(y=0;ycoff[0]...
  • 从一个复数点积算法看NEON的汇编优化  由 技术编辑 于 星期五, 03/21/2014 - 15:05 发表  摘要:本文通过一个真实案例(4096点双精度浮点复数点积算法),描述了使用 Zynq-7000 NEON进行算法...
  • v_regs ldp d14, d15, [sp], #16 ldp d12, d13, [sp], #16 ldp d10, d11, [sp], #16 ldp d8, d9, [sp], #16 .endm arm32位: push {r4-r11, lr} vpush {d8-d15} vpop {d8-d15} pop {r4-r11, pc} 6.2 4x4矩阵转置:...
  • arm64位(aarch64架构): (1)arm寄存器入栈和出栈: 入栈: sub sp, sp, #0x10 stp x8, x9, [sp] // 寄存器成对入栈 出栈: ldp x8, x9, [sp] add sp, sp, #0x10 //寄存器成对出栈 原则:1、...
  • 目录 前言 SIMD简介 ARM NEON Intrinsics简介 函数改写示例 ...最近公司在视频直播项目中要使用H.265/HEVC,具体的是使用HW硬件编码H.264/AVC...因此一个工作就是优化该解码器在手机上的性能表现,主要使用ARM提供..
  • armarm通用指令及优化技巧

    千次阅读 2018-08-15 15:49:14
    参考:https://blog.csdn.net/billbliss/article/details/78929304  ... 一、arm通用指令 通用算术指令: VABA:向量差值绝对值累加、VABD:向量差值绝对值、VABS:向量绝对值、V...
  • Design and Implementation of a Highly Efficient DGEMM for 64-bit ARMv8 Multi-Core Processors 针对64位 ARMv8八核处理器,设计并实现了一种基于 OpenBLAS 的高效 DGEMM。作者首先为此架构开发性能模型,然后...
  • ARM指令详细解释

    千次阅读 2018-03-19 11:20:32
    本人喜欢编程,喜欢计算机,从事算法优化工作,常年使用arm neon,如果有志同道合的朋友,扩展IT圈人脉,遇到技术问题共同探讨,共同进步,欢迎添加微信 mybc_0,或者二维码 转自: ... 在移动平台上进行一些复杂...
  • v11.8H}, [sp] sub sp, sp, #32 ld1 {v8.8H, v9.8H}, [sp] add sp, sp, #128 .endm arm32位: push {r4-r11, lr} vpush {d8-d15} vpop {d8-d15} pop {r4-r11, pc} 3.2 4x4矩阵转置arm64位(aarch64架构)...
  • 如果使用了arm公司提供的neon加速技术,则可以并行的读取多个元素,对多个元素进行操作,虽然时间复杂度还是o(mn),但是常数因子会变小,并且在寄存器里的操作比在普通内存中还要快一些,所以会带来一定的性能提升。...
  • 1. 前言 这是我自己做的移动端算法优化笔记的第一篇文章。我入门移动端的时间其实很...关于这篇文章,其实之前梁德澎作者已经分享过了,即【AI移动端算法优化】二,移动端arm cpu优化学习笔记之一步步优化盒子滤波 ,所
  • ###Date: 2018/1/11 ...   在移动平台上进行一些复杂算法的开发,一般需要用到指令集来进行加速。...ARM是微处理器行业的一家知名企业,其芯片结构有:armv5、armv6、armv7和armv8系列。芯片类型有...
  • ARM与NEON指令加速

    千次阅读 2016-12-06 17:38:38
    目前在移动上使用最多的是ARM芯片。 ARM是微处理器行业的一家知名企业,其芯片结构有:armv5、armv6、armv7和armv8系列。芯片类型有:arm7、arm9、arm11、cortex系列。指令集有:armv5、armv6和neon指令。关于ARM...
  • ARM和NEON指令

    2018-10-26 10:24:14
    目前在移动上使用最多的是ARM芯片。 ARM是微处理器行业的一家知名企业,其芯片结构有:armv5、armv6、armv7和armv8系列。芯片类型有:arm7、arm9、arm11、cortex系列。指令集有:armv5、armv6和neon指令。关于ARM到...
  • Android NDK开发之 ARM与NEON指令说明

    千次阅读 2016-01-07 14:38:20
    原文引自: ... 在移动平台上进行一些复杂算法的开发,一般需要用到指令集来进行加速。目前在移动上使用最多的是ARM芯片。 ARM是微处理器行业的一家知名企业,其芯片结构有:armv5、armv...芯片类型有:arm7、arm9、arm11
  • ,其包含了常用的arm汇编指令类型,如数学运算,逻辑运算等。另外,其引入了有针对性的加载/存储/转置/交叉存取等指令。部分常见的指令在会下面的示例环节中予以说明。需要注意的是,指令中的助记符与arm汇编是...
  • 我们对卷积核进行相同的转换操作,再将得到的卷积核矩阵进行一下转置,就可以进行卷积层的运算操作了。这里 k 是每个卷积核和输入立方体的数值个数,那么假设我们要处理 1 x 3 x 160 x 160 (N x C x H x W)的一张...
  • ARM NEON 简介

    2018-08-29 16:53:00
    ARM NEON 简介 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472j/chr1360928373893.html https://doc.rust-lang.org/nightly/core/arch/arm/index.html ...
  • NEON转置指令 右旋90 4x4矩阵右旋实例 灰度图(单通道)右旋90 彩图(RGB三通道)右旋90 左旋90 4x4矩阵左旋实例 灰度图(单通道)左旋90 彩图(RGB三通道)左旋90 RK3288-linux(硬浮点)耗时对比 前言 ...
  • ARM和neon指令集

    千次阅读 2016-07-20 18:05:58
    目前在移动上使用最多的是ARM芯片。 ARM是微处理器行业的一家知名企业,其芯片结构有:armv5、armv6、armv7和armv8系列。芯片类型有:arm7、arm9、arm11、cortex系列。指令集有:armv5、armv6和neon指令。关于ARM...

空空如也

空空如也

1 2 3 4 5 6
收藏数 112
精华内容 44
热门标签
关键字:

arm汇编实现矩阵转置

友情链接: UART_RING_BUFFER_F446RE.zip