2012-08-09 127 views
4

我開發一個iOS應用程序需要圖片來自RGB轉換 - > BGRA相當迅速。如果可能,我想使用NEON內部函數。有沒有比簡單分配組件更快的方法?使用ARM NEON內在函數添加α和置換

void neonPermuteRGBtoBGRA(unsigned char* src, unsigned char* dst, int numPix) 
{ 
    numPix /= 8; //process 8 pixels at a time 

    uint8x8_t alpha = vdup_n_u8 (0xff); 

    for (int i=0; i<numPix; i++) 
    { 
     uint8x8x3_t rgb = vld3_u8 (src); 
     uint8x8x4_t bgra; 

     bgra.val[0] = rgb.val[2]; //these lines are slow 
     bgra.val[1] = rgb.val[1]; //these lines are slow 
     bgra.val[2] = rgb.val[0]; //these lines are slow 

     bgra.val[3] = alpha; 

     vst4_u8(dst, bgra); 

     src += 8*3; 
     dst += 8*4; 
    } 


} 

回答

9

的ARMCC拆卸不是那麼快可以:

  • 它不使用最合適的指令

  • 它結合了NEON那些引起巨大的打嗝每次

試試這個VFP指令:

mov r2, r2, lsr #3 
    vmov.u8, d3, #0xff 
loop: 
    vld3.8 {d0-d2}, [r0]! 
    subs r2, r2, #1 
    vswp d0, d2 
    vst4.8 {d0-d3}, [r1]! 
    bgt loop 

    bx lr 

我建議的代碼也未完全優化,但進一步的「真實」優化會嚴重損害可讀性。所以我停下來。

+0

無法將其轉換爲llvm內聯彙編。必須將'vmov.u8,d3,#0xff'更改爲'vmov.u8 d3,#0xff'。用上面的函數包裝時仍然會導致崩潰。有任何想法嗎? – 2012-08-16 05:32:49

+0

'空隙neonPermuteRGBtoBGRA_gas(無符號字符* SRC,無符號字符* DST,整數numPix) { __asm__易失性( 「MOV R2,R2,LSR#3 \ n」 個 「VMOV。#0xff \ n「 」loop:\ n「 」vld3.8 {d0-d2},[r0]!\ n「 」subs r2,r2,#1 \ n「 」vswp d0, D2 \ n」個 「vst4.8 {D0-D3},[R1] \ n」 個 「BGT環\ n」 個 「BX LR \ n」 個 );! } #endif' – 2012-08-16 05:34:12

+0

我沒有」牛逼器armcc要求應該是最優化的。我是想,如果你使用的NEON內在,你是在編譯器的手說。 – auselen 2012-08-17 08:32:01

7

這取決於編譯器。例如,當我編譯代碼與上面器armcc(5.01)和拆解,我所得到的樣子(我只是把循環,我感動的循環之外阿爾法分配)

18: f420440d vld3.8 {d4-d6}, [r0]! 
    1c: e2822001 add r2, r2, #1 ; 0x1 
    20: eeb01b45 fcpyd d1, d5 
    24: eeb00b46 fcpyd d0, d6 
    28: eeb02b44 fcpyd d2, d4 
    2c: f401000d vst4.8 {d0-d3}, [r1]! 
    30: e1520003 cmp r2, r3 
    34: bafffff7 blt 18 <neonPermuteRGBtoBGRA_armcc+0x18> 

如果我編譯與海灣合作委員會(4.4.3),並再次我得到拆解代碼,

40: f967 040f vld3.8 {d16-d18}, [r7] 
    44: 46d6  mov lr, sl 
    46: ecca 0b06 vstmia sl, {d16-d18} 
    4a: 9d02  ldr r5, [sp, #8] 
    4c: ed8d 8b1a vstr d8, [sp, #104] 
    50: 3718  adds r7, #24 
    52: e8be 000f ldmia.w lr!, {r0, r1, r2, r3} 
    56: f108 0801 add.w r8, r8, #1 ; 0x1 
    5a: c50f  stmia r5!, {r0, r1, r2, r3} 
    5c: eddd 0b24 vldr d16, [sp, #144] 
    60: e89e 0003 ldmia.w lr, {r0, r1} 
    64: edcd 0b16 vstr d16, [sp, #88] 
    68: eddd 0b22 vldr d16, [sp, #136] 
    6c: edcd 0b18 vstr d16, [sp, #96] 
    70: e885 0003 stmia.w r5, {r0, r1} 
    74: ed9d 0b26 vldr d0, [sp, #152] 
    78: 9d03  ldr r5, [sp, #12] 
    7a: ed8d 0b14 vstr d0, [sp, #80] 
    7e: cd0f  ldmia r5!, {r0, r1, r2, r3} 
    80: 46ae  mov lr, r5 
    82: 465d  mov r5, fp 
    84: c50f  stmia r5!, {r0, r1, r2, r3} 
    86: e89e 000f ldmia.w lr, {r0, r1, r2, r3} 
    8a: e885 000f stmia.w r5, {r0, r1, r2, r3} 
    8e: 9501  str r5, [sp, #4] 
    90: 465d  mov r5, fp 
    92: 2100  movs r1, #0 
    94: 2220  movs r2, #32 
    96: 4620  mov r0, r4 
    98: f7ff fffe bl 0 <memset> 
    9c: cd0f  ldmia r5!, {r0, r1, r2, r3} 
    9e: 4625  mov r5, r4 
    a0: c50f  stmia r5!, {r0, r1, r2, r3} 
    a2: f8dd c004 ldr.w ip, [sp, #4] 
    a6: e89c 000f ldmia.w ip, {r0, r1, r2, r3} 
    aa: e885 000f stmia.w r5, {r0, r1, r2, r3} 
    ae: ecd4 0b08 vldmia r4, {d16-d19} 
    b2: f946 000f vst4.8 {d16-d19}, [r6] 
    b6: 3620  adds r6, #32 
    b8: 45c8  cmp r8, r9 
    ba: dbc1  blt.n 40 <memset+0x40> 

和執行時間與更快器armcc 10倍。

如果我編譯生成器armcc彙編代碼的函數(它看起來像現在阿爾法是早在循環:))與海灣合作委員會(內聯彙編)

void neonPermuteRGBtoBGRA_gas(unsigned char* src, unsigned char* dst, 
    int numPix) { 
    asm(
      "  ASR  r3,r2,#31\n" 
      "  VMOV.I8 d1,#0xff\n" 
      "  ADD  r2,r2,r3,LSR #29\n" 
      "  ASR  r3,r2,#3\n" 
      "  MOV  r2,#0\n" 
      "  CMP  r3,#0\n" 
      "  BLE  end\n" 
      "loop:\n" 
      "  VLD3.8 {d4,d5,d6},[r0]!\n" 
      "  ADD  r2,r2,#1\n" 
      "  CMP  r3,r2\n" 
      "  VMOV.F64 d3,d5\n" 
      "  VMOV.F64 d2,d6\n" 
      "  VMOV.F64 d5,d1\n" 
      "  VMOV.F64 d0,d4\n" 
      "  VST4.8 {d2,d3,d4,d5},[r1]!\n" 
      "  BGT  loop\n" 
      "end:\n" 
      ); 
    } 

我得到相同的執行時間與海灣合作委員會,以及。

在到底是什麼,我建議你要麼拆卸您的二進制和檢查編譯器生成你想要什麼,或者使用匯編。

順便說一句,如果你想進一步提高這個函數的執行時間,我建議你去看看

  1. 手臂的PLD(預加載數據)指令
  2. 利用所有的循環可能NEON指令像循環展開(你會發現,實際帶寬將內存中的數據加載時間)
+4

哦由GCC生成的代碼NEON恐怖.. – 2012-08-10 15:01:12

+3

用戶喜歡你是我喜歡棧溢出了這麼多的原因。我從來沒有想過要嘗試ARM C編譯器(這是我第一次不得不優化代碼)。謝謝! – 2012-08-10 17:05:21