X86 AVX或SSE上的水平尾随最大值

X86 AVX或SSE上的水平尾随最大值,x86,sse,simd,avx,avx2,X86,Sse,Simd,Avx,Avx2,我有一个由16位值组成的_m256i寄存器,我想得到每个尾随元素的最大值,即零 举个例子: input: 1 0 0 3 0 0 4 5 0 0 0 0 4 3 0 2 output: 1 1 1 3 3 3 4 5 5 5 5 5 4 3 3 2 在AVX或AVX架构上有没有有效的方法来实现这一点?可能使用log(16)=4次迭代 补充: 对于包含8个uint_16的128位数字的任何解决方案,我们也非常感谢。您确实可以在log_2(SIMD_宽度)步骤中完成此操作。其思想是将输入向量移动

我有一个由16位值组成的_m256i寄存器,我想得到每个尾随元素的最大值,即零

举个例子:

input:  1 0 0 3 0 0 4 5 0 0 0 0 4 3 0 2
output: 1 1 1 3 3 3 4 5 5 5 5 5 4 3 3 2
在AVX或AVX架构上有没有有效的方法来实现这一点?可能使用log(16)=4次迭代

补充:
对于包含8个uint_16的128位数字的任何解决方案,我们也非常感谢。

您确实可以在
log_2(SIMD_宽度)
步骤中完成此操作。其思想是将输入向量移动两个字节。然后我们混合
x_-vec
带有移位向量,使得
x_-vec
被移位向量替换,但仅在
x_-vec
的零位置。 此过程以4、8和16字节的移位重复。您可以取消注释代码中的
printf
-s,以查看
x_vec
x_trail
之间发生了什么

#包括
#包括
/*gcc-O3-Wall-m64-march=broadwell-falign回路=16水平轨道最大c*/
int print_vec_short(__m256ix);
__m256i水平传输最大值(m256i x vec){
__m256i零=_mm256_setzero_si256();
__m256i pshufb_cnst=_mm256_set_epi64x(0x808080,0x80808080,0x0F0E0E0E,0x0F0E0E);
__m256i mask1=_mm256_cmpeq_epi16(x_vec,零);
__m256i t1=_mm256_slli_si256(x_vec,2);/*_mm256_slli_si256()不穿过128b车道*/
__m256i t2=mm256 blendv_epi8(x_vec,t1,mask1);
__m256i mask3=_mm256_cmpeq_epi16(t2,零);
__m256i t3=_mm256_slli_si256(t2,4);
__m256i t4=mm256 blendv\u epi8(t2、t3、mask3);
__m256i mask5=_mm256_cmpeq_epi16(t4,零);
__m256i t5=mm256 slli si256(t4,8);
__m256i t6=mm256 blendv_epi8(t4、t5、mask5);
__m256i mask7=_mm256_cmpeq_epi16(t6,零);
__m256i t7_0=_mm256_shuffle_epi8(t6,pshufb_cnst);/*_mm256_slli_si256()不跨越128b边界。因此,我们需要在此处进行无序排列和置换*/
__m256i t7_1=_mm256_permute2x128_si256(t7_0,t7_0,0x01);/*t7_1={t6[7],t6[7],…,t6[7],0,0,0,0,0,0}*/
__m256i x_trail=_mm256_blendv_epi8(t6、t7_1、mask7);
/*取消对下面几行的注释以打印中间变量的值*/
/*
printf(“\n15…0=15 14 13 12 11 10 9 8 7 6 5 4 3 2 10\n”);
printf(“x_vec=”);print_vec_short(x_vec);printf(“mask1=”);print_vec_short(mask1);
printf(“t1=”);print_vec_short(t1);printf(“t2=”);print_vec_short(t2);
printf(“mask3=”);print_vec_short(mask3);printf(“t3=”);print_vec_short(t3);
printf(“t4=”);print_vec_short(t4);printf(“mask5=”);print_vec_short(mask5);
printf(“t5=”);print_vec_short(t5);printf(“t6=”);print_vec_short(t6);
printf(“mask7=”);print_vec_short(mask7);printf(“t7_0=”);print_vec_short(t7_0);
printf(“t7_1=”);print_vec_short(t7_1);printf(“x_trail=”);print_vec_short(x_trail);printf(“\n”);
*/
返回x_轨迹;
}
int hor_tr_max_n(短int*x_in,短int*x_out,int n){
__m256i减1=_mm256_set1_epi8(-1);
__m256i零=_mm256_setzero_si256();
__m256i pshufb_cnst=_mm256_set_epi64x(0x808080,0x80808080,0x0F0E0E0E,0x0F0E0E);
int indx_last_nz=0;
对于(int i=0;i>1;
__m256i x_last_nz=_mm256_广播w_epi16(_mmuload_si128((_m128i*)和x_in[indx_last_nz]);
indx_last_nz=mvmsk_nonz?(i+15-lz_x_vec):indx_last_nz;
__m256i x_tr_is_zero=_mm256_cmpeq_epi16(x_trail,zero);
__m256i x_trail\u upd=\u mm256\u blendv\u epi8(x_trail,x_last\u nz,x_tr_为零);
_mm256_-store_-si256((u-m256i*)和x_-out[i],x_-trail\u-upd);
}
返回0;
}
int main(){
#定义测试0
#如果测试==0
printf(“测试0:测试功能\n”);
短x[16]={1,0,0,3,0,0,4,5,0,0,0,0,4,3,0,2};
//短x[16]={0,0,0,3,0,0,4,5,0,0,0,0,4,3,0,2};
//短x[16]={1,0,0,3,0,0,4000,0,0,0,10,0,0,0,3,0,2};
//短x[16]={1100,0,0,0,0,0,0,0,0,0,0,0,0,0,5000,0,0,0,0};
//短x[16]={1100,0,0,0,0,0,0,0,8888,0,0,0,0,0,5000,0,0,0,0};
printf(“\n15…0=15 14 13 12 11 10 9 8 7 6 5 4 3 2 10\n”);
__m256i x_vec=_mm256_loadu_si256((u m256i*)x);
printf(“x_vec=”);print_vec_short(x_vec);
__m256i x_trail=水平最大值(x_vec);
printf(“x_trail=”);print_vec_short(x_trail);
#elif测试==1 | |测试==2
int i,i_o,k;
int n=8000;
int d=50;
短int*x_in;
短int*x_out;
x_in=_mm_malloc(n*sizeof(short int),32);
x_out=_mm_malloc(n*sizeof(short int),32);
int j=73659343;/*生成一个伪随机数组a*/
对于(i=0;i>8;/*k是介于0和1023之间的伪随机数*/
如果(k15...0     =   15   14   13   12     11   10    9    8      7    6    5    4       3    2    1    0
x_vec      =    2    0    3    4 |    0    0    0    0 |    5    4    0    0  |    3    0    0    1
x_trail    =    2    3    3    4 |    5    5    5    5 |    5    4    3    3  |    3    1    1    1
short int prev_x  = 0;
for (i=0;i<n;i=i+4){
    short int x_in_i0 = x_in[i];                                                     
    short int x_in_i1 = x_in[i+1];                                                   
    short int x_in_i2 = x_in[i+2];                                                   
    short int x_in_i3 = x_in[i+3];                                                   
              prev_x  = (x_in_i0)?(x_in_i0):(prev_x);  x_out[i]   = prev_x;           
              prev_x  = (x_in_i1)?(x_in_i1):(prev_x);  x_out[i+1] = prev_x;           
              prev_x  = (x_in_i2)?(x_in_i2):(prev_x);  x_out[i+2] = prev_x;           
              prev_x  = (x_in_i3)?(x_in_i3):(prev_x);  x_out[i+3] = prev_x;           
}