Arm 如何选择霓虹灯矢量的所有车道

Arm 如何选择霓虹灯矢量的所有车道,arm,intrinsics,neon,Arm,Intrinsics,Neon,我想使用NEON Intrinsic优化以下代码 uint32x4_t c1; // 4 elements, each element is 0 or 1 uint32x4_t c2; // 4 elements, each element is 0 or 1 uint8_t pack = 0; // unsigned char, for result /* some code /* // need optimizing pack |= (vgetq_lane_u32(c1, 0); pac


我想使用NEON Intrinsic优化以下代码

uint32x4_t c1; // 4 elements, each element is 0 or 1
uint32x4_t c2; // 4 elements, each element is 0 or 1
uint8_t pack = 0; // unsigned char, for result

/* some code /*

// need optimizing
pack |= (vgetq_lane_u32(c1, 0);
pack |= (vgetq_lane_u32(c1, 1) << 1;
pack |= (vgetq_lane_u32(c1, 2) << 2;
pack |= (vgetq_lane_u32(c1, 3) << 3;


pack |= (vgetq_lane_u32(c2, 0) << 4;
pack |= (vgetq_lane_u32(c2, 1) << 5;
pack |= (vgetq_lane_u32(c2, 2) << 6;
pack |= (vgetq_lane_u32(c2, 3) << 7;
uint32x4\u t c1;//4个元素,每个元素为0或1
uint32x4_t c2;//4个元素,每个元素为0或1
uint8\u t pack=0;//无符号字符,用于结果
/*一些代码/*
//需要优化
pack |=(vgetq_lane_u32(c1,0);

pack |=(vgetq_lane_u32(c1,1)您可以将向量中的每个元素移位各个位数

const int32x4_t shifter1 = {0, 1, 2, 3};
const int32x4_t shifter2 = {4, 5, 6, 7};
.
.
.
c1 = vshlq_u32(c1, shifter1);
c2 = vshlq_u32(c2, shifter2);

c1 = vorrq_u32(c1, c2);
pack |= vgetq_lane_u32(c1, 0) | vgetq_lane_u32(c1, 1) | vgetq_lane_u32(c1, 2) | vgetq_lane_u32(c1, 3);

这就应该做到了,最后一行取决于编译器的质量。您可以将向量中的每个元素按各自的位数进行移位

const int32x4_t shifter1 = {0, 1, 2, 3};
const int32x4_t shifter2 = {4, 5, 6, 7};
.
.
.
c1 = vshlq_u32(c1, shifter1);
c2 = vshlq_u32(c2, shifter2);

c1 = vorrq_u32(c1, c2);
pack |= vgetq_lane_u32(c1, 0) | vgetq_lane_u32(c1, 1) | vgetq_lane_u32(c1, 2) | vgetq_lane_u32(c1, 3);

这就应该做到了,最后一行取决于编译器的质量

通常对于像ADD或or这样的关联水平缩减,您将高半部分提取到并合并,然后重复,直到只剩下一个元素。取log2(N_元素)步骤。当然,在开始使用水平运算将宽度减半之前,您可以将两个向量垂直合并为一个向量。哦,我刚刚注意到,您希望每个车道的移位计数不同,因此您希望将8x 32位
bool
元素打包到位图中。我的注释前面的注释基于标题。顺便说一句,如果您实际上,你有0/-1个向量比较结果向量,你可以先使用它们,而不是用
&1
屏蔽它们。通常,对于像ADD或or这样的关联水平缩减,你将高半部提取到并合并,然后重复,直到只剩下一个元素。取log2(N_个元素)步骤。当然,在开始使用水平运算将宽度减半之前,您可以将两个向量垂直合并为一个向量。哦,我刚刚注意到,您希望每个车道的移位计数不同,因此您希望将8x 32位
bool
元素打包到位图中。我的注释前面的注释基于标题。顺便说一句,如果您实际上,你有0/-1个向量比较结果向量,你可以先用
&1
来屏蔽它们。
pack=0
开始,这样你就可以写
pack=…
而不是
pack=…
。即使对于第一个SIMD元素,使用
=
这个操作也很奇怪。@PeterCordes
/*一些代码*/应该包含那个部分。:-)内在的vgetq_通道很慢,我不想使用它。@shang12
vgetq_通道
不慢,但是是的,它有大约14个周期的巨大延迟(
vmov
到ARM寄存器)如果你需要
pack
作为
uint8\u t
进行进一步的计算,那就没有办法了。如果你只是想把它存储到内存中,把它保存在NEON寄存器中是有意义的。既然你声明
pack
作为
uint8\u t
,我觉得后者不可行。答案只能和你的问题一样好。没有人可以在线阅读或猜测你的想法。我正在计算一个二进制图像。每个循环将产生一个像素(0或1),我将在一个字节中打包8个像素。感谢您的帮助!我将使用此解决方案。
pack=0
开始时,您可以编写
pack=…
而不是
pack=…
。即使对于第一个SIMD元素,OP在使用
=
时也很奇怪。@PeterCordes
/*一些代码*/
应该包含这一点部分:-)内部vgetq_-lane很慢,我不想使用它。@shang12
vgetq_-lane
不慢,但是是的,它有大约14个周期的巨大延迟(
vmov
到ARM寄存器)。这一切都归结到下一步。如果您需要
pack
作为
uint8\u t
进行进一步计算,那么没有办法。如果您只想将其存储到内存中,将其保存在NEON寄存器中是有意义的。由于您将
pack
声明为
uint8\u t
,我认为后者不可行。答案只能和你的问题一样好。没有人可以在线阅读或猜测你的想法。我正在计算一个二进制图像。每个循环将产生一个像素(0或1),我将在一个字节中打包8个像素。谢谢你的帮助!我将使用这个解决方案。