Łuk*_*Lew 8 x86 assembly intrinsics
是否有任何asm指令可以加速Core i7架构上双精度/整数向量的最小值/最大值的计算?
更新:
我没想到会有如此丰富的答案,谢谢.所以我看到max/min可以不分支.我有一个小问题:
有没有一种有效的方法来获得阵列中最大的双倍索引?
Pet*_*ham 12
SSE4具有PMAXSD或PMAXUD用于32位有符号/无符号整数,这可能很有用.
SSE2具有MAXPD并且MAXSD在两对之间和之间进行比较,因此您使用一个MAXSD跟随n/2-1 MAXPD以获得n的向量的最大值,通常是负载和操作的交错.
有以上的MIN等价物.
对于双重案例,在SSE模式下,你可能不会在汇编程序方面做得比半合适的C++编译器更好:
peregrino:$ g++ -O3 src/min_max.cpp -o bin/min_max
peregrino:$ g++ -O3 -msse4 -mfpmath=sse src/min_max.cpp -o bin/min_max_sse
peregrino:$ time bin/min_max
0,40
real 0m0.874s
user 0m0.796s
sys 0m0.004s
peregrino:$ time bin/min_max_sse
0,40
real 0m0.457s
user 0m0.404s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
其中min_max使用朴素循环计算500次双倍100,000次的最小值和最大值:
bool min_max ( double array[], size_t len, double& min, double& max )
{
double min_value = array [ 0 ];
double max_value = array [ 0 ];
for ( size_t index = 1; index < len; ++index ) {
if ( array [ index ] < min_value ) min_value = array [ index ];
if ( array [ index ] > max_value ) max_value = array [ index ];
}
min = min_value;
max = max_value;
}
Run Code Online (Sandbox Code Playgroud)
为了响应第二部分,从max操作中删除分支的传统优化是比较值,将标志作为单个位(给出0或1),减去1(给出0或0xffff_ffff)和'和'来表示两个可能结果的xor,所以你得到相当于( a > best ? ( current_index ^ best_index ) : 0 ) ^ best_index ).我怀疑有一种简单的SSE方式,只是因为SSE倾向于对打包值而不是标记值进行操作; 有一些水平索引操作,所以你可以尝试找到最大值,然后从原始向量中的所有元素中减去它,然后收集符号位,零符号将对应于最大值的索引,但这可能是除非你使用短路或字节,否则不是改进.