遍历集合时,说一个Point
的向量,其中Point
是保存x
,y
,z
数据的某种结构或某物,当我需要一次将这些点转换为另一种类型的点时,我是否应该认为它像副本一样昂贵?
例如,如果我有一个vector<Point> v
,我显然会尽量避免:
vector<OtherPointType> vo;
// populate v
std::transform(v.begin(), v.end(), vo.begin(),
[](Point const& p) { return OtherPointType{p.x, p.y, p.z}; });
SomeOperation(vo); // Can only operate on vector<OtherPointType>
但是,这和这样做一样昂贵吗?
for_each(..., [](Point const& p)
{
OtherPointType opt(p.x, p.y, p.z);
SomeOperation(opt); // Can only operator on `OtherPointType`
});
?
我的直觉是,因为后者是没有任何动态分配的静态副本,所以它应该不昂贵,但我认为问这个问题很重要。
通常,在后一种情况下,我可以使用类似Eigen::Map
之类的东西,但是即使在那儿,我仍然要写两个int
(在栈上),我认为是由于Eigen::Stride
(是在这种情况下,这甚至是一个好的解决方案?)但是然后,像CGAL这样的库就没有映射功能了,我很好奇与之合作的好方法。
请注意,我的工作通常每秒处理一百万个点,因此,我要尽量减少昂贵的副本,这一点很重要。
更新
在一个子问题中,我想知道Eigen::Map
是否适合上述后一种情况:
我运行了一个benchmark,并且至少在gcc 5.4上,即使有1亿点,结果也难以接近。使用Eigen::Map
vs 构造Eigen::Vector3d
分别花费了276 ms和285 ms。尽管构建所需的时间更少,但是点数更少,这告诉我,区别在于不确定性内,计算机上运行的其他进程可能会产生更大的影响。
答案 0 :(得分:4)
我应该认为[转换]和复制一样昂贵吗?
因为它是不同的操作,所以不一定。它可能或多或少地昂贵。但是,将其与副本进行比较是合理的。
但是[复制向量]和[迭代向量并将每个元素复制到自动变量中]一样昂贵
可能不是。
我的直觉是,因为后者是没有任何分配的静态副本,所以它不应该昂贵
这就是为什么后者可能不比前者贵的原因。但是后者是否昂贵取决于上下文。仍然是线性渐进复杂度的运算,因此如果向量很大,则与副本相比,分配可能微不足道。
某些东西是否比硬件上的其他东西要贵,以及某些东西在程序上下文中是否很昂贵,您可以尝试使用探查器来查找。