我想知道在3D矢量的每个元素上执行方法的最快方法是什么。
假设我们有:
std::vector<vector<vector<CLS>>> myVec;
我希望尽可能以最快的方式执行以下循环:
for(int cycle=0;cycle<10;cycle++) // do it 10 times
{
for(int i=0;i<myVec.size();i++)
{
for(int j=0;j<myVec[i][constant].size();j++)
{
foo(myVec[i][constant][j]);
}
}
}
在我的案例中,很好地提到中期指数总是常数。 是否足够快地使用std :: vector或建议使用其他类型的容器?
期待您的帮助。谢谢
答案 0 :(得分:2)
以下会更快:
for(int i=0, int vecSize = myVec.size();i<vecSize;i++)
{
for(int j=0, int currentLineSize = myVec[i][constant].size();j<currentLineSize;j++)
{
foo(myVec[i][constant][j]);
//copy-paste this 10 times instead of having the outer loop
}
}
如果您对尺寸有所了解,可以再展开一次。
答案 1 :(得分:2)
迭代器的使用应该更快(在foo
的每次调用时都不必查看整个数组。)
typedef std::vector<CLS> v1;
typedef std::vector<v1> v2;
typedef std::vector<v2> v3;
for(int cycle=0;cycle<10;cycle++) // do it 10 times
{
for(v3::const_iterator itOuter = myVec.begin(); itOuter != myVec.end(); ++itOuter)
{
const v1& vec = (*itOuter)[constant];
for(v1::const_iterator itInner = vec.begin(); itInner != vec.end(); ++itInner)
foo(*itInner);
}
}
我没有测量它(虽然甚至没有尝试编译,所以原谅任何错别字)
答案 2 :(得分:1)
可能“尽可能快的方式”(以及最少的C ++ - 可能的方式,尽管它仍然是有效的C ++)将沿着这些方向:
const unsigned dim1 = 10; //first dimension
const unsigned dim2 = 20; //second
const unsigned dim3 = 30; //third
const unsigned nElem = dim1 * dim2 * dim3;
CLS myVec[nElem];
CLS *p = myVec, *q = myVec + nElem;
while (p < q)
{ foo(*p);
++p;
}
这消除了索引的所有计算,因为foo()
似乎仅取决于所讨论的CLS
元素的值,而不取决于它在数组中的位置。当然,以3D方式访问myVec
变得更加复杂(myVec[x * dim1 * dim2 + y * dim1 + z]
等等 - 只是明确了C ++通常为您做的所有索引计算......)。
更改循环以“切片”数组以使一个维度保持不变会使它更复杂一些(实际上使它成为一个双嵌套循环,在内循环终点处为指针添加一个额外的偏移量)。有点像这样(虽然我可能有相反的尺寸):
while (p < q)
{ CLS *r = p + dim3;
while (p < r)
{ foo(*p);
++p;
}
p += dim2;
}
答案 3 :(得分:0)
您可以创建一个递归函数对象:
class Foo {
public:
template<typename Container>
void operator()(Container& container) {
for_each(container.begin(), container.end(), *this);
}
void operator()(CLS cls) {
// do what you want
}
};
Foo foo;
foo(myVec);
答案 4 :(得分:0)
如果你想要效率,为什么要在3个循环中完成?
这是一个1
int cycle,
i = 0,
j = 0,
counter;
for(cycle = 0, counter = 0; cycle < 10; counter++)
{
j = counter % myVec[i][constant].size(); // It will go between 0 - myVec[i][constant].size()
i += (!j) * !(!counter); // If j is reset (j =
i %= myVec.size();
foo(myVec[i][constant][j]); // Do your function
cycle += (!i) * (!j) * !(!counter);
}
j = counter % myVec[i][constant].size()
它将介于0
到myVec[i][constant].size()
i += (!j) * !(!counter)
如果重置j
(j
等于0
),请将其设为1
,但如果{ {1}} counter
是0
= !(!0)
= !1
},如果它比0
更大,那么0
例如5
{1}} = !(!5)
= !0
)所以1
增加1
i
它将在i %= myVec.size()
到0
之间转换,并在到达myVec.size()
时重新开始i = 0
myVec.size()
你的功能
foo(myVec[i][constant][j])
如果重置cycle += (!i) * (!j) * !(!counter)
(i
等于i
),请将其设为0
,1
相同但如果j
大于counter
,0
增加1