问如何累加一个128位寄存器中的四个float数?

问题(zlw):

一个_mm128型的寄存器包含  (xx3, xx2, xx1, xx0)这样四个float型浮点数.

想做 xx0 + xx1 + xx2 + xx3这样的计算

提问者自己觉得可以用:
xx = _mm_hadd_ps(xx, _mm_set_zero);    // to get (0, 0, xx3+ xx2, xx1+xx0)

 xx= _mm_add_ss(xx, _mm_shuffle_ps(xx,xx, _MM_SHUFFLE( 0, 0, 0, 1 )) ); 
_mm_store_ss(&temp,xx); 

亦可以用:

xx= _mm_add_ps(xx, _mm_movehl_ps(xx, xx));

xx= _mm_add_ss(xx, _mm_shuffle_ps(xx, xx, 1));

_mm_store_ss( &temp, xx );

问有没有更好的方法?

 

回答1(jimdempseyatthecove):

对同一寄存器使用两次hadd(源和目的寄存器为同一个)
// xx = { xx3, xx2, xx1, xx0 }
xx=_mm_hadd_ps(xx,xx);
// xx = { xx3+xx2, xx1+xx0, xx3+xx2, xx1+xx0}
xx=_mm_hadd_ps(xx,xx);
// xx = { xx2+xx3+xx1+xx0, xx3+xx2+xx1+xx0, xx3+xx2+xx1+xx0, xx3+xx2+xx1+xx0}

虽然最终每个32位里都是四个float型数的累加和,但是并不会带来额外开销
需要额外注意的是,如果在比较老的处理器上使用,需要在两次水平累加中间插入一个load或者store或者非sse操作(why?)

回答2(Brandon Hewitt):

“最好”的方法依赖实现的平台。

(这里用到了 Intel® Cilk™ Plus )

 

使用Intel C++ Composer XE Update 2 版本的编译器,产生的默认 Intel® SSE2代码如下 (i.e. icc -S -c test.c), :

movups (%rdi), %xmm0

movaps %xmm0, %xmm1

movhlps %xmm0, %xmm1

addps %xmm1, %xmm0

movaps %xmm0, %xmm2

shufps $245, %xmm0, %xmm2

addss %xmm2, %xmm0

ret


而支持 Intel SSE4.2 (icc -xSSE4.2 -S -c test.c)平台,则会得到
movups (%rdi), %xmm0

haddps %xmm0, %xmm0

haddps %xmm0, %xmm0

ret

这个查看Cilk汇编指令的方法很好。

Intel对自家产品的优化应该尽心尽力,一般手工优化能达到这样的水平应该说还算不错的。

 

P.S.//20110807

http://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/cpp/mac/optaps/common/optaps_par_cean_prog.htm

C/C++ Extensions for Array Notations Programming Model

 

Reductions

A reduction combines array section elements to generate a scalar result. Intel® Cilk™ Plus supports reductions on array sections. It defines a generic reduction function that applies a user-defined dyadic function. It also has nine built-in common reduction functions. The built-in functions are polymorphic functions that accept int, float, and other C basic data type arguments. The names and descriptions of reduction functions are summarized in the table below.

Reduction Function Prototypes
Function PrototypesDescriptions
__sec_reduce(fun, identity, a[:]) Generic reduction function. Reduces fun across the array a[:] using identity as the initial value.
__sec_reduce_add(a[:]) Built-in reduction function. Adds values passed as arrays
__sec_reduce_mul(a[:]) Built-in reduction function. Multiplies values passed as arrays
__sec_reduce_all_zero(a[:]) Built-in reduction function. Tests that array elements are all zero
__sec_reduce_all_nonzero(a[:])Built-in reduction function. Tests that array elements are all non-zero
__sec_reduce_any_nonzero(a[:]) Built-in reduction function. Tests for any array element that is non-zero
__sec_reduce_min(a[:]) Built-in reduction function. Determines the minimum value of array elements
__sec_reduce_max(a[:]) Built-in reduction function. Determines the maximum value of array elements
__sec_reduce_min_ind(a[:]) Built-in reduction function. Determines the index of minimum value of array elements
__sec_reduce_max_ind(a[:])Built-in reduction function. Determines the index of maximum value of array elements

The reduction operation can reduce on multiple ranks. The number of ranks reduced depends on the execution context. For a given execution context of rank m and a reduction array section argument with rank n, where n>m, the last n-m ranks of the array section argument are reduced.

Example
sum = __sec_reduce_add(a[:][:]); // sum across the whole array a
sum_of_column[:] = __sec_reduce_add(a[:][:]); // sum across the column of a

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值