Optimization 有没有迭代的方法来计算沿扫描线的半径?
我正在处理一系列具有相同Y值但不同X值的点。我通过将X增加1来遍历这些点。例如,Y=50,X是-30到30之间的整数。我的算法的一部分涉及到从每个点到原点的距离,然后做进一步的处理 分析之后,我发现距离计算中的sqrt调用占用了我大量的时间。有没有迭代的方法来计算距离 换言之: 我想有效地计算:Optimization 有没有迭代的方法来计算沿扫描线的半径?,optimization,mathematical-optimization,Optimization,Mathematical Optimization,我正在处理一系列具有相同Y值但不同X值的点。我通过将X增加1来遍历这些点。例如,Y=50,X是-30到30之间的整数。我的算法的一部分涉及到从每个点到原点的距离,然后做进一步的处理 分析之后,我发现距离计算中的sqrt调用占用了我大量的时间。有没有迭代的方法来计算距离 换言之: 我想有效地计算:r[n]=sqrt(x[n]*x[n]+y*y))。我可以保存上一次迭代的信息。每次迭代都会增加x,因此x[n]=x[n-1]+1。我不能使用sqrt或trig函数,因为它们太慢了,除了在每个扫描线的开头
r[n]=sqrt(x[n]*x[n]+y*y))
。我可以保存上一次迭代的信息。每次迭代都会增加x,因此x[n]=x[n-1]+1
。我不能使用sqrt或trig函数,因为它们太慢了,除了在每个扫描线的开头
我可以使用近似值,只要它们足够好(误差小于0.1%),并且引入的误差是平滑的(我不能使用预先计算的近似值表)
其他信息:
x和y始终是介于-150和150之间的整数
明天我将尝试几个想法,并根据哪个答案最快来标记最佳答案
结果
我做了一些计时
- 距离公式:16毫秒/次
- Pete的interperlating解决方案:8 ms/次
- wrang-wrang预计算解决方案:8ms/迭代
Y=10000
Y2=Y*Y
for x=0..Y2 do
D[x]=sqrt(Y2+x*x)
norm(x,y)=
if (y==0) x
else if (x>y) norm(y,x)
else {
s=Y/y
D[round(x*s)]/s
}
如果你的坐标是平滑的,那么这个想法可以通过线性插值来扩展。要获得更高的精度,请增加Y
其思想是s*(x,y)在y=y线上,这是您预先计算的距离。求出距离,然后除以s
我想你真的需要距离,而不是它的平方
您可能还可以找到一个通用的sqrt实现,它牺牲了一些精度来提高速度,但我很难想象它能打败FPU
通过线性插值,我的意思是将D[round(x)]
更改为:
f=floor(x)
a=x-f
D[f]*(1-a)+D[f+1]*a
如果你的坐标是平滑的,那么这个想法可以通过线性插值来扩展。要获得更高的精度,请增加Y
其思想是s*(x,y)在y=y线上,这是您预先计算的距离。求出距离,然后除以s
我想你真的需要距离,而不是它的平方
您可能还可以找到一个通用的sqrt实现,它牺牲了一些精度来提高速度,但我很难想象它能打败FPU
通过线性插值,我的意思是将D[round(x)]
更改为:
f=floor(x)
a=x-f
D[f]*(1-a)+D[f+1]*a
这并不能真正回答你的问题,但可能会有帮助 我要问的第一个问题是:
- “我需要sqrt吗?”
- “如果没有,我如何减少SQRT的数量?”
- 然后是你的:“我可以用一个聪明的计算替换剩余的SQRT吗?”
- 您需要确切的半径,还是半径平方可以接受?sqrt有快速近似,但可能不够精确,无法满足您的规格
- 你能用镜像象限或八分之一来处理图像吗?通过批量处理相同半径值的所有像素,可以将计算数量减少8倍
- 你能预先计算半径值吗?您只需要一个大小为您正在处理的图像大小的四分之一(或者可能是八分之一)的表,并且该表只需要预先计算一次,然后在多次运行算法时重复使用
因此,聪明的数学可能不是最快的解决方案。这并不能真正回答你的问题,但可能有助于 我要问的第一个问题是:
- “我需要sqrt吗?”
- “如果没有,我如何减少SQRT的数量?”
- 然后是你的:“我可以用一个聪明的计算替换剩余的SQRT吗?”
- 您需要确切的半径,还是半径平方可以接受?sqrt有快速近似,但可能不够精确,无法满足您的规格
- 你能用镜像象限或八分之一来处理图像吗?通过批量处理相同半径值的所有像素,可以将计算数量减少8倍
- 你能预先计算半径值吗?您只需要一个大小为您正在处理的图像大小的四分之一(或者可能是八分之一)的表,并且该表只需要预先计算一次,然后在多次运行算法时重复使用
因此,聪明的数学可能不是最快的解决方案。好吧,你可以从x=0开始镜像(你只需要计算n>=0,然后将这些结果复制到相应的n好吧,你可以从x=0开始镜像(您只需计算n>=0,并将这些结果复制到相应的n好吧,总是有人试图优化您的sqrt,我见过的最快的是旧的carmack quake 3 sqrt:
这就是说,由于sqrt是非线性的,您无法沿着直线进行简单的线性插值来获得结果。最好的方法是使用表格查找,因为这将使您能够快速访问数据。而且,由于您似乎是按整数进行迭代,所以表格查找应该非常准确。ll总是在尝试优化您的sqrt,我见过的最快的是旧的carmack quake 3 sqrt: 这就是说,由于sqrt是非线性的,您无法沿着直线进行简单的线性插值来获得结果。最好的方法是使用表格查找,因为这将使您能够快速访问数据。而且,由于您似乎是按整数进行迭代,所以应该使用表格查找
x: 0 r_true: 50.000000 r_approx: 50.000000 error: 0.000000%
x: 1 r_true: 50.010000 r_approx: 50.009999 error: 0.000002%
....
x: 29 r_true: 57.825065 r_approx: 57.801384 error: 0.040953%
x: 30 r_true: 58.335225 r_approx: 58.309519 error: 0.044065%
NEW X = OLD X - epsilon * OLD Y
NEW Y = OLD Y + epsilon * NEW(!) X