gpt4 book ai didi

c - NEON 中非统一地址跳转的实现

转载 作者:行者123 更新时间:2023-11-30 15:56:30 25 4
gpt4 key购买 nike

我需要在 Neon 中实现以下循环。

int jump=4,c[8],i;  //c[8] may be declared here
int *src,sum=0; //**EDIT:** src points to a 256 element array

for (i = 0; i < 4; i++)
{
sum = src[ i + 0 * jump] * c[0];//1
sum += src[ i + 1 * jump] * c[1];//2
sum += src[ i + 2 * jump] * c[2];//3
sum += src[ i + 3 * jump] * c[3];//4
sum += src[ i + 4 * jump] * c[4];//5
sum += src[ i + 5 * jump] * c[5];//6
sum += src[ i + 6 * jump] * c[6];//7
sum += src[ i + 7 * jump] * c[7];//8


src += 2; //9
}

**EDIT:**
The code can be shortened as-

int jump=4,c[8],i,j; //initialize array c
int *src,sum,a[256];//initialize array a
src=a;
for (i = 0; i < 4; i++)
{
sum=0;
for (j = 0; j < 8; j++)
{
int *p=src+ i + (j * jump);
sum += (*p)* c[j]; //sum += src[ i + j* jump] * c[j]
}
printf("Sum:%d\n",sum);
src += 2;
}


Just need to know a way to implement something like [%0]=[%0]+4 rather than [%0]!

主要优化将通过使用 NEON 中的 VMLA 指令并行运行编号 1-8 的指令来实现。

  1. 我们可以通过将数组 c[8] 加载到寄存器 q0 和 q1 并将数组 src[256] 加载到寄存器 q2 和 q3 来实现这一点。之后,我们使用 VMLA、VADD、VPADD 来获取变量 sum 中的结果。
  2. 面临的问题如何加载数组 src 的元素(如 src[0]、src[4]、src[8] 等)因为我知道如何加载数组的唯一方法是通过 [%1]!它仅按顺序加载数组(如 src[0]、src[1]、src[2] 等)。

另外指令 9 中指针 src 如何加 2

最佳答案

不要依次计算总和,而是同时计算它们。那么您不需要跳过源值,因为每个源值(大概)都会影响一些总和。基本上,您所做的就是计算(* 表示点积)。

sum0 = source * (c0 0 0  0 c1 0  0  0 c2 0  0  0 ... c7  0 0  0 )
sum1 = source * ( 0 0 0 c0 0 0 0 c1 0 0 0 c2 ... 0 0 0 c7 )
sum2 = source * ( 0 0 0 0 0 0 c0 0 0 0 c1 0 ... 0 0 c6 0 )
sum3 = source * ( 0 0 0 0 0 0 0 0 0 c0 0 0 ... 0 c5 0 0 )

你可以通过这样做来做到这一点

sum0 = sum1 = sum2 = sum3 = 0

sum0 += (s0 s1 s2 s3) * (c0 0 0 0)
sum1 += (s0 s1 s2 s3) * ( 0 0 0 c0)
sum2 += (s0 s1 s2 s3) * ( 0 0 0 0)
sum3 += (s0 s1 s2 s3) * ( 0 0 0 0)

sum0 += (s0 s1 s2 s3) * (c1 0 0 0)
sum1 += (s0 s1 s2 s3) * ( 0 0 0 c1)
sum2 += (s0 s1 s2 s3) * ( 0 0 c0 0)
sum3 += (s0 s1 s2 s3) * ( 0 0 0 0)

...

sum0 += (s0 s1 s2 s3) * (c7 0 0 0)
sum1 += (s0 s1 s2 s3) * ( 0 0 0 c7)
sum2 += (s0 s1 s2 s3) * ( 0 0 c6 0)
sum3 += (s0 s1 s2 s3) * ( 0 c5 0 0)

您实际上不需要在各个步骤中进行水平求和,您只需使用 vmul.32 (或者可能是累积形式,如果有的话)来计算点积,然后在最后对它们进行水平求和。您只需要找出一种方法来计算系数 vector ,但由于它们都只有一个非零元素,因此您可以简单地使用 vset_lane。

或者,更好的是,您可以利用每个系数 vector 仅包含一个非零条目的事实,并执行一个乘法而不是四个,然后使用 vdup_lane 提取每个 channel 并将其添加到总和中。您需要生成系数 vector

(c0  0  0  0)
(c1 0 c0 c1)
(c2 c0 c1 c2)
...
(c7 c5 c6 c7)

如果您的系数已经连续存储,这应该很容易 - 您只需要修复第一个元素。

关于c - NEON 中非统一地址跳转的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11224679/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com