请考虑以下问题:
我的问题是:如何优化以下独立功能:
// Computation of the coordinates of P
inline std::array<double, 3> P(const std::array<double, 3>& A,
const std::array<double, 3>& B,
const std::array<double, 3>& M)
{
// The most inefficient version in the world (to be verified)
std::array<double, 3> AB = {B[0]-A[0], B[1]-A[1], B[2]-A[2]};
std::array<double, 3> AM = {M[0]-A[0], M[1]-A[1], M[2]-A[2]};
double norm = std::sqrt(AB[0]*AB[0]+AB[1]*AB[1]+AB[2]*AB[2]);
double dot = AB[0]*AM[0]+AB[1]*AM[1]+AB[2]*AM[2];
double d1 = dot/norm;
std::array<double, 3> AP = {AB[0]/d1, AB[1]/d1, AB[2]/d1};
std::array<double, 3> P = {AP[0]-A[0], AP[1]-A[1], AP[2]-A[2]};
return P;
}
// Computation of the distance d0
inline double d0(const std::array<double, 3>& A,
const std::array<double, 3>& B,
const std::array<double, 3>& M)
{
// The most inefficient version in the world (to be verified)
std::array<double, 3> AB = {B[0]-A[0], B[1]-A[1], B[2]-A[2]};
std::array<double, 3> AM = {M[0]-A[0], M[1]-A[1], M[2]-A[2]};
double norm = std::sqrt(AB[0]*AB[0]+AB[1]*AB[1]+AB[2]*AB[2]);
double dot = AB[0]*AM[0]+AB[1]*AM[1]+AB[2]*AM[2];
double d1 = dot/norm;
std::array<double, 3> AP = {AB[0]/d1, AB[1]/d1, AB[2]/d1};
std::array<double, 3> P = {AP[0]-A[0], AP[1]-A[1], AP[2]-A[2]};
std::array<double, 3> MP = {P[0]-M[0], P[1]-M[1], P[2]-M[2]};
double d0 = std::sqrt(MP[0]*MP[0]+MP[1]*MP[1]+MP[2]*MP[2]);
return d0;
}
// Computation of the distance d1
inline double d1(const std::array<double, 3>& A,
const std::array<double, 3>& B,
const std::array<double, 3>& M)
{
// The most inefficient version in the world (to be verified)
std::array<double, 3> AB = {B[0]-A[0], B[1]-A[1], B[2]-A[2]};
std::array<double, 3> AM = {M[0]-A[0], M[1]-A[1], M[2]-A[2]};
double norm = std::sqrt(AB[0]*AB[0]+AB[1]*AB[1]+AB[2]*AB[2]);
double dot = AB[0]*AM[0]+AB[1]*AM[1]+AB[2]*AM[2];
double d1 = dot/norm;
}
// Computation of the distance d2
inline double d2(const std::array<double, 3>& A,
const std::array<double, 3>& B,
const std::array<double, 3>& M)
{
// The most inefficient version in the world (to be verified)
std::array<double, 3> AB = {B[0]-A[0], B[1]-A[1], B[2]-A[2]};
std::array<double, 3> AM = {M[0]-A[0], M[1]-A[1], M[2]-A[2]};
double norm = std::sqrt(AB[0]*AB[0]+AB[1]*AB[1]+AB[2]*AB[2]);
double dot = AB[0]*AM[0]+AB[1]*AM[1]+AB[2]*AM[2];
double d1 = dot/norm;
double d2 = norm-d1;
return d2;
}
这样每个函数都会被尽可能地优化?(我会执行这些函数亿万次)。
4条答案
按热度按时间pb3skfrl1#
从算法的Angular 来看,您可以计算向量到另一个向量的投影,而不使用SQRT调用
这里伪码http://www.euclideanspace.com/maths/geometry/elements/line/projections/
其中dot()是两个向量的点积,len_squared是向量与self的点积。
注:如果可能,尝试在主循环之前预先计算v2_ls的倒数。
q9rjltbz2#
一次计算所有请求数量可能更好。
设
P = A + t . AB
为给出P
位置的矢量方程,表示MP
和AB
正交:MP . AB = 0 = (MA + t . AB) . AB
,其产生t= - (MA . AB) / AB^2
和P
。t
是比率AP / AB
,因此d1 = t . |AB|
。类似地,d2 = (1 - t) . |AB|
.d0
是从毕达哥拉斯d0^2 = MA^2 - d1^2
获得的,或者通过|MP|
的直接计算获得。会计:计算
MA
(增加3个),AB
(增加3个),AB^2
(2次添加,3 μ l),MA.AB
(2次添加,3 μ l),t
(1格),P
(3个加法器,3微升),|AB|
(1平方),d1
(1微升),d2
(1个加法器,1微升),MA^2
(2个加法器,3微升),d0
(1个加法器,1微升,1平方)。总共17个加法器,15个乘法器,1个除法器,2个平方。
exdqitrt3#
如果您希望代码可移植,因此不使用处理器特定的功能,我建议您:
1)正如我在上面的评论中提到的,创建一个3D矢量类,它只会使编写代码变得容易得多(优化开发时间)
2)创建一个交集类,使用惰性求值来获取P、d0和d1,如下所示:
3)不要调用10亿次,什么都不做会无限快,为什么要调用这么频繁,有没有方法可以用更少的调用来求出P、d0和d1?
如果您可以使用处理器特定的特性,那么您可以考虑使用SIMD,但这可能需要将精度从双精度降至浮点。
q3qa4bjr4#
以下是点到线投影计算的C++实现