为什么 boost::geometry::distance 和 model::d2::point_xy<float> returns 是 double 而不是 float?
Why boost::geometry::distance with model::d2::point_xy<float> returns a double not a float?
我将 boost::geometry::distance
在 model::d2::point_xy<float>
参数上的性能与等效的直接 2D 实现进行了比较:
struct Point {
float x, y;
float distance(const Point& p) const {return sqrt((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y));}
};
(请参阅 http://rextester.com/NTOVR83857 处的整个基准测试)。我发现 boost 版本在所有主要的 C++ 编译器中始终较慢:
- gcc 为 1.77x
- 1.47x for clang
- 1.51 倍 vc++
我用 double
点坐标尝试了相同的基准测试,其中执行了没有开销的提升。我注意到 boost::geometry::distance
with model::d2::point_xy<float>
arguments returns a double
,这似乎是减速的原因。为什么它不返回 float
?
由于boost使用的是模板,所以需要保证return类型有足够的精度。想象一下,如果输入 Points 具有 X 和 Y 的整数值——结果需要的不仅仅是整数精度。此外,如果输入点对 X 和 Y 使用双精度值,则 float
的结果将不够精确。因此,似乎选择 double
作为具有足够精度的包罗万象。
此处给出距离模板设计的基本原理:
http://www.boost.org/doc/libs/1_58_0/libs/geometry/doc/html/geometry/design.html
return 类型取决于策略:http://www.boost.org/doc/libs/1_58_0/libs/geometry/doc/html/geometry/design.html#geometry.design.return_type。
这使我认为您可以通过策略明确指定计算类型:
#include <iostream>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/strategies/distance.hpp>
int main() {
using namespace boost::geometry;
using P = model::d2::point_xy<float>;
using V = traits::coordinate_type<P>::type;
std::cout << "Coordinate type: " << typeid(V).name() << "\n";
P a, b;
std::cout << "Calculation type: " << typeid(default_distance_result<P, P>::calculation_type).name() << "\n";
std::cout << "Result type: " << typeid(default_distance_result<P, P>::type).name() << "\n";
using S = strategy::distance::pythagoras<V>;
std::cout << "Calculation type: " << typeid(distance_result<P, P, S>::calculation_type).name() << "\n";
std::cout << "Result type: " << typeid(distance_result<P, P, S>::type).name() << "\n";
static_assert(boost::is_same<distance_result<P, P, S>::type, float>::value, "oops");
}
打印(通过管道 c++filt -t
):
Coordinate type: float
Calculation type: boost::geometry::strategy::distance::pythagoras<void>::calculation_type<boost::geometry::model::d2::point_xy<float, boost::geometry::cs::cartesian>, boost::geometry::model::d2::point_xy<float, boost::geometry::cs::cartesian> >
Result type: double
Calculation type: boost::geometry::strategy::distance::pythagoras<float>::calculation_type<boost::geometry::model::d2::point_xy<float, boost::geometry::cs::cartesian>, boost::geometry::model::d2::point_xy<float, boost::geometry::cs::cartesian> >
Result type: float
注意结果精度可能会因为精度有限而被削减。这在很大程度上是 precision/storage 效率权衡。
我实际上希望 double
无处不在(而不是 float
),尤其是对现代 CPU 指令集进行全面优化时,性能最好。
我将 boost::geometry::distance
在 model::d2::point_xy<float>
参数上的性能与等效的直接 2D 实现进行了比较:
struct Point {
float x, y;
float distance(const Point& p) const {return sqrt((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y));}
};
(请参阅 http://rextester.com/NTOVR83857 处的整个基准测试)。我发现 boost 版本在所有主要的 C++ 编译器中始终较慢:
- gcc 为 1.77x
- 1.47x for clang
- 1.51 倍 vc++
我用 double
点坐标尝试了相同的基准测试,其中执行了没有开销的提升。我注意到 boost::geometry::distance
with model::d2::point_xy<float>
arguments returns a double
,这似乎是减速的原因。为什么它不返回 float
?
由于boost使用的是模板,所以需要保证return类型有足够的精度。想象一下,如果输入 Points 具有 X 和 Y 的整数值——结果需要的不仅仅是整数精度。此外,如果输入点对 X 和 Y 使用双精度值,则 float
的结果将不够精确。因此,似乎选择 double
作为具有足够精度的包罗万象。
此处给出距离模板设计的基本原理:
http://www.boost.org/doc/libs/1_58_0/libs/geometry/doc/html/geometry/design.html
return 类型取决于策略:http://www.boost.org/doc/libs/1_58_0/libs/geometry/doc/html/geometry/design.html#geometry.design.return_type。
这使我认为您可以通过策略明确指定计算类型:
#include <iostream>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/strategies/distance.hpp>
int main() {
using namespace boost::geometry;
using P = model::d2::point_xy<float>;
using V = traits::coordinate_type<P>::type;
std::cout << "Coordinate type: " << typeid(V).name() << "\n";
P a, b;
std::cout << "Calculation type: " << typeid(default_distance_result<P, P>::calculation_type).name() << "\n";
std::cout << "Result type: " << typeid(default_distance_result<P, P>::type).name() << "\n";
using S = strategy::distance::pythagoras<V>;
std::cout << "Calculation type: " << typeid(distance_result<P, P, S>::calculation_type).name() << "\n";
std::cout << "Result type: " << typeid(distance_result<P, P, S>::type).name() << "\n";
static_assert(boost::is_same<distance_result<P, P, S>::type, float>::value, "oops");
}
打印(通过管道 c++filt -t
):
Coordinate type: float
Calculation type: boost::geometry::strategy::distance::pythagoras<void>::calculation_type<boost::geometry::model::d2::point_xy<float, boost::geometry::cs::cartesian>, boost::geometry::model::d2::point_xy<float, boost::geometry::cs::cartesian> >
Result type: double
Calculation type: boost::geometry::strategy::distance::pythagoras<float>::calculation_type<boost::geometry::model::d2::point_xy<float, boost::geometry::cs::cartesian>, boost::geometry::model::d2::point_xy<float, boost::geometry::cs::cartesian> >
Result type: float
注意结果精度可能会因为精度有限而被削减。这在很大程度上是 precision/storage 效率权衡。
我实际上希望 double
无处不在(而不是 float
),尤其是对现代 CPU 指令集进行全面优化时,性能最好。