改变端倪,工会比移位更有效吗?

布伦丹·里乌斯(Brendan Rius)

有人要求我改变一个整数的内在性。我当时的想法是使用移位

int    swap_endianess(int color)
{
    int a;
    int r;
    int g;
    int b;

    a = (color & (255 << 24)) >> 24;
    r = (color & (255 << 16)) >> 16;
    g = (color & (255 << 8)) >> 8;
    b = (color & 255)
    return (b << 24 | g << 16 | r << 8 | a);
}

但是有人告诉我,使用包含一个int和四个字符的数组的联合会更容易(如果一个int存储在4个字符上),填充int然后反转该数组。

union   u_color
{
  int   color;
  char  c[4];
};

int             swap_endianess(int color)
{
  union u_color ucol;
  char          tmp;

  ucol.color = color;
  tmp = ucol.c[0];
  ucol.c[0] = ucol.c[3];
  ucol.c[3] = tmp;
  tmp = ucol.c[1];
  ucol.c[1] = ucol.c[2];
  ucol.c[2] = tmp;
  return (ucol.color);
}

在这两者之间交换字节的更有效方法是什么?有更有效的方法吗?

编辑

在I7上进行测试后,联合方式大约需要24秒(用time命令测量),而移位方式在2,000,000,000次迭代中大约需要15秒。如果我使用-O1进行编译,则这两种方法仅需1秒,而使用-O2或-O3只需0.001秒。

位偏移方法bswap在ASM中使用-02和-03编译,但不是联合方式,gcc似乎可以识别幼稚的模式,但不能识别复杂的联合方式。最后,请阅读@ user3386109的底行。

用户名

这是字节交换功能的正确代码

uint32_t changeEndianess( uint32_t value )
{
    uint32_t r, g, b, a;

    r = (value >> 24) & 0xff;
    g = (value >> 16) & 0xff;
    b = (value >>  8) & 0xff;
    a =  value        & 0xff;

    return (a << 24) | (b << 16) | (g << 8) | r;
}

这是一个测试字节交换功能的功能

void testEndianess( void )
{
    uint32_t value = arc4random();
    uint32_t result = changeEndianess( value );
    printf( "%08x %08x\n", value, result );
}

通过全面优化使用LLVM编译器,该testEndianess函数的最终汇编代码为

0x93d0:  calll  0xc82e                    ; call `arc4random`
0x93d5:  movl   %eax, %ecx                ; copy `value` into register CX
0x93d7:  bswapl %ecx                 ; <--- this is the `changeEndianess` function
0x93d9:  movl   %ecx, 0x8(%esp)           ; put 'result' on the stack
0x93dd:  movl   %eax, 0x4(%esp)           ; put 'value' on the stack
0x93e1:  leal   0x6536(%esi), %eax        ; compute address of the format string
0x93e7:  movl   %eax, (%esp)              ; put the format string on the stack
0x93ea:  calll  0xc864                    ; call 'printf'

换句话说,LLVM编译器识别整个changeEndianess功能并将其实现为单个bswapl指令。


对于那些想知道为什么需要调用的人的旁注arc4random给定此代码

void testEndianess( void )
{
    uint32_t value = 0x11223344;
    uint32_t result = changeEndianess( value );
    printf( "%08x %08x\n", value, result );
}

编译器生成该程序集

0x93dc:  leal   0x6524(%eax), %eax        ; compute address of format string 
0x93e2:  movl   %eax, (%esp)              ; put the format string on the stack
0x93e5:  movl   $0x44332211, 0x8(%esp)    ; put 'result' on the stack
0x93ed:  movl   $0x11223344, 0x4(%esp)    ; put 'value' on the stack
0x93f5:  calll  0xc868                    ; call 'printf'

换句话说,给定一个硬编码value作为输入,编译器的预计算result的的changeEndianess功能,并提出其直接进入汇编代码,完全绕过功能。


底线。以编写代码的合理方式编写代码,然后让编译器进行优化。这些天的编译器很棒。在源代码中使用棘手的优化(例如,并集)可能会破坏编译器中内置的优化,从而导致代码变慢。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

有更有效的方法吗?

来自分类Dev

更有效的.RData吗?

来自分类Dev

分块数组更有效吗?

来自分类Dev

更有效的书写方式吗?

来自分类Dev

更有效的布局可能吗?

来自分类Dev

字节比布尔[8]更有效吗?

来自分类Dev

在MATLAB中更有效的对称方阵的方式吗?

来自分类Dev

for(auto && e:a)比for(auto&e:a)更有效吗?

来自分类Dev

这种多线程单例更有效吗?

来自分类Dev

我可以使用更有效的查询吗

来自分类Dev

这样在Go中会更有效吗?

来自分类Dev

++运算符比a = a + 1更有效吗?

来自分类Dev

使用setState或setProps对于Reactjs更有效吗?

来自分类Dev

这个python代码可以更有效吗?

来自分类Dev

知道如何使这段代码更有效吗?

来自分类Dev

使用向量对比使用向量对更有效吗?

来自分类Dev

用ccCircle画圆更有效吗?

来自分类Dev

求模数比And运算符更有效吗

来自分类Dev

数组公式或单个公式更有效吗?

来自分类Dev

使用工会而不是在Apache Spark中加入会更有效,还是没关系?

来自分类Dev

哪个更有效?

来自分类Dev

使循环更有效

来自分类Dev

更有效的循环

来自分类Dev

使循环更有效

来自分类Dev

赋值会改变变量的有效类型吗?

来自分类Dev

管道,移位或参数扩展是否更有效率?

来自分类Dev

在jgrapht中修剪有向无环图的更有效方法吗?

来自分类Dev

什么是排序算法?还有更有效的方法吗?

来自分类Dev

执行更有效的COUNT