【发布时间】:2015-07-07 00:56:50
【问题描述】:
我正在处理点云数据(每个云 150k 点)。我想,对于每个 (x,y) 点,计算到参考点 O 的距离和方位角:
for each point p in points
dx = p.x - ox
dy = p.y - oy
d = hypot(dx, dy)
az = atan2(dy, dx)
我有一个手动 SSE 实施。我希望使用 eigen 使代码更清晰:
ArrayXf x(points.size()), y(points.size());
for(unsigned i=0; i<points.size(); ++i) {
x[i] = points[i].x;
y[i] = points[i].y;
}
const ArrayXf d = (dx.square() + dy.square()).sqrt();
// implement a polynomial approximation to atan (same as the SSE)
但是,从我的计时实验来看,这似乎根本没有矢量化,因为时间与基线实现相同。而且我知道 SSE2 已启用,因为我在同一个文件中编译了一些 SSE2 代码。
但是,根据文档,Eigen 在支持时确实利用了 SSE2(以及 3.3 中的 AVX)。是不是只针对向量和矩阵运算?
编辑:我研究了生成的汇编代码,它确实包含一些 SSE 指令。但是还是很慢
编辑:这里有更多时间信息。我正在循环超过 100 帧,每帧大约 150k 点。
- 没有 atan2 的简单实现:150 毫秒
- sse 实现(处理 4 x 4 点并丢弃最后几个未填充完整数据包的点):30 毫秒
- 使用特征图的特征实现:90 毫秒(差异:36 毫秒,假设:16 毫秒,索引:17 毫秒)
这是我的特征码:
const Eigen::Map<const Eigen::ArrayXf, Eigen::Unaligned, Eigen::InnerStride<4> > px(&(points[0].x), points.size());
const Eigen::Map<const Eigen::ArrayXf, Eigen::Unaligned, Eigen::InnerStride<4> > py(&(points[0].y), points.size());
// difference with the origin (ox and oy are floats)
const Eigen::ArrayXf dx = px - ox, dy = py - oy;
// distance and index
const Eigen::ArrayXf d = sqrt(dx.square() + dy.square());
static const float r_res_mult = 1.0f / r_res; //2x faster than div
const Eigen::ArrayXi didx = (d * r_res_mult).cast<int>();
【问题讨论】:
-
您需要
sqrt吗?你能用平方距离代替吗? -
请注意,这个问题超出了这个问题:我正在研究尽可能轻松地利用 SIMD 的选项,然后我会将其应用于大量代码。