Optimization 有没有迭代的方法来计算沿扫描线的半径?

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函数,因为它们太慢了,除了在每个扫描线的开头

我正在处理一系列具有相同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函数,因为它们太慢了,除了在每个扫描线的开头

我可以使用近似值,只要它们足够好(误差小于0.1%),并且引入的误差是平滑的(我不能使用预先计算的近似值表)

其他信息: x和y始终是介于-150和150之间的整数

明天我将尝试几个想法,并根据哪个答案最快来标记最佳答案

结果

我做了一些计时

  • 距离公式:16毫秒/次
  • Pete的interperlating解决方案:8 ms/次
  • wrang-wrang预计算解决方案:8ms/迭代
我希望考试能在两者之间做出决定,因为我喜欢这两个答案。我要去Pete's,因为它占用的内存更少

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