简体   繁体   English

c ++在3D矢量上最快的循环扫描

[英]c++ fastest loop scan over 3D vector

I want to know what is the fastest way as possible to perform a method on each element of a 3D vector. 我想知道在3D矢量的每个元素上执行方法的最快方法是什么。

Suppose we have: 假设我们有:

std::vector<vector<vector<CLS>>> myVec;

I want to do the following loops in the fastest way as possible: 我想以最快的方式执行以下循环:

 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]);
       }

    } 
 }

It's well mentioning that the middle term index is always constant in my case. 值得一提的是,在我的案例中,中期指数总是不变的 Is using std::vector fast enough or you suggest another type container? 是否足够快地使用std :: vector或者你建议使用另一种类型的容器?

Looking forward to your help.Thanks 期待您的帮助。谢谢

The following would be faster: 以下会更快:

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
   }
} 

If you know anything about the sizes, you can perform some more unrolling. 如果您对尺寸有所了解,可以执行更多展开。

Usage of iterators should be faster (you don't have to look up through the whole array on every call of foo ). 迭代器的使用应该更快(在每次调用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);
    }
}

I didn't measure it, though (didn't even try to compile, so pardon any typos) 我没有测量它(虽然甚至没有尝试编译,所以原谅任何错别字)

Probably the "fastest way possible" (and the least C++-ish way possible, although it's still valid C++) would be along these lines: 可能“尽可能快的方式”(以及最少的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;
}

This eliminates all the calculation of indices, since foo() seems to depend only on the value of the CLS element in question, not on its position in the array. 这消除了索引的所有计算,因为foo()似乎仅取决于所讨论的CLS元素的值,而不取决于它在数组中的位置。 Of course, accessing myVec in a 3D-ish way becomes more complex ( myVec[x * dim1 * dim2 + y * dim1 + z] and so on - just making explicit all the indexing calculations C++ normally does for you...). 当然,以3D方式访问myVec变得更加复杂( myVec[x * dim1 * dim2 + y * dim1 + z]等等 - 只是明确了C ++通常为你做的所有索引计算...)。

Changing the loop around to "slice" the array so that one dimension is kept constant would make it a little more complicated (essentially make it a doubly nested loop that adds an additional offset to the pointer at the termination of the inner loop). 更改循环以“切片”数组以使一个维度保持不变将使其更复杂一些(实质上使其成为双嵌套循环,在内循环终止处向指针添加额外的偏移量)。 A bit like this (although I may have the dimensions reversed): 有点像这样(虽然我可能有相反的尺寸):

while (p < q)
{ CLS *r = p + dim3;
  while (p < r)
  { foo(*p);
    ++p;
  }
  p += dim2;
}

You could create a recursive function object: 您可以创建一个递归函数对象:

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);

Why would you do it in 3 loops if you want efficiency? 如果你想要效率,为什么要在3个循环中完成?

Here is in one 1 这是一个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() It will go between 0 to myVec[i][constant].size() j = counter % myVec[i][constant].size()它将介于0myVec[i][constant].size()

i += (!j) * !(!counter) If j is reset ( j is equal to 0 ) so make it 1 , but if counter is 0 so ( !(!0) = !1 = 0 ) and if it's bigger then 0 so 5 for example ( !(!5) = !0 = 1 ) so i being increasd by 1 i += (!j) * !(!counter)如果j被复位( j等于0 )所以使它为1如果counter0!(!0) = !1 = 0 )并且如果它是大于0所以5例如( !(!5) = !0 = 1 )因此i增加1

i %= myVec.size() It Will Go between 0 to myVec.size() and start again ( i = 0 ) when reached myVec.size() i %= myVec.size()它将介于0myVec.size()之间,并在到达myVec.size()时再次启动( i = 0 myVec.size()

foo(myVec[i][constant][j]) Your function foo(myVec[i][constant][j])你的功能

cycle += (!i) * (!j) * !(!counter) If i is reset ( i is equal to 0 ) so make it 1 ,same for j but if counter is bigger then 0 , cycle being increasd by 1 cycle += (!i) * (!j) * !(!counter)如果i复位( i等于0 ),则将其设为1 ,对于j为相同如果counter大于0 ,则cycle增加1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM