Chinaunix首页 | 论坛 | 博客
  • 博客访问: 243282
  • 博文数量: 33
  • 博客积分: 2511
  • 博客等级: 少校
  • 技术积分: 391
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-06 09:24
文章分类
文章存档

2011年(3)

2010年(9)

2009年(3)

2008年(18)

我的朋友

分类: LINUX

2008-07-24 17:51:20

1. ordinary c language level
#define avg2(a,b)     ((a+b+1)>>1)
#define avg4(a,b,c,d)     ((a+b+c+d+2)>>2)
显而易见.注意a,b宏表达式可能引出的副作用

2.SIMD by software
实现方法1:
inline static uint64_t BYTE_VEC(uint64_t x)
{
    x |= x <<  8;
    x |= x << 16;
    x |= x << 32;
    return x;
}
static inline uint64_t avg2_no_rnd(uint64_t a, uint64_t b)
{
    return (a & b) + (((a ^ b) & BYTE_VEC(0xfe)) >> 1);
}
static inline uint64_t avg2(uint64_t a, uint64_t b)
{
    return (a | b) - (((a ^ b) & BYTE_VEC(0xfe)) >> 1);
}

实现方法2:
#define op_avg_round(a,b)  a = ( ((a)|(b)) - ((((a)^(b))&0xFEFEFEFEUL)>>1) )
#define op_avg_noround(a,b)  a = ( ((a)&(b)) + ((((a)^(b))&0xFEFEFEFEUL)>>1) )
通过软件实现 singl instruction multi data,单指令多数据流,上述实现方法一样方法1
实现8个8bits宽度数据的同时平均,在64位cpu上使用方法2实现4个8bits宽度数据的同时平
均,在32位cpu上使用,简单对此加以分析加法结果有2个成分,1个是进位,1个是逻辑
和((a)&(b))<<1是进位 (((a)^(b))是逻辑和((a)&(b))<<1 + (((a)^(b))&0xFEFEFEFEUL)
为和,各自右移一位得到平均值,之所以是0xFE,因为把每个字节的最后一个bit置零以
免移位时进入下一个字节影响下一个字节的值((a)| (b)) 对应位在 0 1,1 0,1 1的3种
情况下都得到1,所以((a)|(b))<<1 表示进位+非满进位,因为在0 1,1 0这种情况下也产
生了进位,刚好是它的逻辑和,其他分析同上

3. machine instruction level
AMD 3DNOW 指令:
#define AVG_3DNOW_OP(a,b,temp, size) \
"mov" #size " " #b ", " #temp "   \n\t"\
"pavgusb " #temp ", " #a "        \n\t"\
"mov" #size " " #a ", " #b "      \n\t"

intel MMX指令:
#define AVG_MMX2_OP(a,b,temp, size) \
"mov" #size " " #b ", " #temp "   \n\t"\
"pavgb " #temp ", " #a "          \n\t"\
"mov" #size " " #a ", " #b "      \n\t"

BTW:http://blog.csdn.net/weixianlin/archive/2008/05/01/2358024.aspx
阅读(1631) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~