SSE4 有 PMAXSD 或 PMAXUD 用于 32 位有符号/无符号整数,这可能很有用。
SSE2 有MAXPD 和MAXSD,它们在成对的双精度之间进行比较,因此您可以按照 n/2-1 MAXPD 和一个 MAXSD 来获得 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
其中 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;
}
针对第二部分,从最大操作中删除分支的传统优化是比较值,将标志作为单个位(给出 0 或 1),减一(给出 0 或 0xffff_ffff)和 'and ' 它与两个可能结果的异或,所以你得到相当于( a > best ? ( current_index ^ best_index ) : 0 ) ^ best_index )。我怀疑是否有一种简单的 SSE 方法可以做到这一点,仅仅是因为 SSE 倾向于对打包值而不是标记值进行操作;有一些水平索引操作,所以你可以尝试找到最大值,然后从原始向量中的所有元素中减去它,然后收集符号位,零符号位将对应于最大值的索引,但这可能除非您使用短裤或字节,否则不会有任何改进。