[英]c++ fastest loop scan over 3D vector
我想知道在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或者你建議使用另一種類型的容器?
期待您的幫助。謝謝
以下會更快:
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
}
}
如果您對尺寸有所了解,可以執行更多展開。
迭代器的使用應該更快(在每次調用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);
}
}
我沒有測量它(雖然甚至沒有嘗試編譯,所以原諒任何錯別字)
可能“盡可能快的方式”(以及最少的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;
}
您可以創建一個遞歸函數對象:
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);
如果你想要效率,為什么要在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
, 但如果counter
為0
( !(!0)
= !1
= 0
)並且如果它是大於0
所以5
例如( !(!5)
= !0
= 1
)因此i
增加1
i %= myVec.size()
它將介於0
和myVec.size()
之間,並在到達myVec.size()
時再次啟動( i = 0
myVec.size()
foo(myVec[i][constant][j])
你的功能
cycle += (!i) * (!j) * !(!counter)
如果i
復位( i
等於0
),則將其設為1
,對於j
為相同但如果counter
大於0
,則cycle
增加1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.