我想使用SIMD (SSE2等)来优化以下函数:
int64_t fun(int64_t N, int size, int* p)
{
int64_t sum = 0;
for(int i=1; i<size; i++)
sum += (N/i)*p[i];
return sum;
}这似乎是一个非常可向量化的任务,除了所需的指令就是不在那里……
我们可以假设N非常大(10^12到10^18),大小约为sqrt(N)。我们还可以假设p只能取-1,0和1的值;所以我们不需要实数乘法,只要我们能以某种方式计算N/i,(N/i)*pi就可以用四条指令(pcmpgt,pxor,psub,pand)来完成。
发布于 2010-11-05 08:06:59
1/x的派生词是-1/x^2,意思是x越大,N/x==N/(x + 1)越大。
对于已知的N/x值(让我们将该值称为r),我们可以确定x的下一个值(让我们将该值称为x',以便N/x'<r
x'= N/(r - 1)由于我们处理的是整数:
x'= ceiling(N/(r - 1))因此,循环如下所示:
int64_t sum = 0;
int i=1;
int r= N;
while (i<size)
{
int s= (N + r - 1 - 1)/(r - 1);
while (i<s && i<size)
{
sum += (r)*p[i];
++i;
}
r= N/s;
}
return sum; 对于足够大的N,您将有许多运行的相同的N/i值。诚然,如果你不小心,你会被零除。
https://stackoverflow.com/questions/4047319
复制相似问题