算术得到3D矢量索引

时间:2014-01-29 19:27:02

标签: c++ optimization memory-management vector struct

我有一个结构的3d矢量。我通过结构的i j和k来指示结构在3d向量中的位置。但是,当制作数百万个这样的内容时,它占用了大量内存,因为该对象存储了大量数据。

如何有效地找出特定结构对象的i,j,k,而不将该信息存储在结构本身中。我可以用某种记忆算法吗?

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main() {
    struct MyStruct {
        size_t i;
        size_t j;
        size_t k;
        bool some_bool;
    };

    vector<vector<vector<MyStruct>>> three_d_struct_v;

    size_t max_i = 1000000;
    size_t max_j = 10;
    size_t max_k = 10;

    for(size_t i = 0; i < max_i; i++) {
        for(size_t j = 0; j < max_j; j++) {
            for(size_t k = 0; k < max_k; k++) {
                three_d_struct_v.emplace_back(MyStruct{i,j,k,false});
            }
        }
    }


    return 0;
}

3 个答案:

答案 0 :(得分:1)

使用真实数组执行此操作的方法非常简单。多级std::vector<>不会这样做,因为所有不同行向量分配的内存不是连续的。但是使用语言的内置数组,这很简单:

//Get the memory
bool myData* = new bool[max_i*max_j*max_k];
inline size_t getIndex(size_t i, size_t j, size_t k) { return (i*max_j + j)*max_k + k; }
inline size_t getI(size_t index) { return index/max_j/max_k; }
inline size_t getJ(size_t index) { return (index/max_k)%max_j; }
inline size_t getK(size_t index) { return index%max_k; }

现在,您可以像谈论指向结构的指针一样讨论索引。如果你真的必须用C ++方式,你可以像这样转换引用和索引:

bool& referenceToElement = myData[anIndex];
size_t recoveredIndex = &referenceToElement - myData;

然而,在C中你可以做得更好:

bool (*myData)[max_j][max_k] = malloc(max_i*sizeof(*myData));
myData[i][j][k] = true;    //True 3D array access!

myData[i][j][k]执行的计算与上面C ++示例中myData[getIndex(i, j, k)]的计算完全相同。并且,和以前一样,您可以使用指针算法检索索引。

C ++也有多维数组,但它要求数组维度为编译时常量(并且您需要使用new而不是malloc())。在C中,没有这样的限制,可以在运行时计算数组大小。

答案 1 :(得分:0)

这是你在找什么?您可以将m视为所有max_i * max_j * max_k结构的索引。

这是未经测试的。在div类型上调用size_t时,您可能需要进行一些投射。

#include <cstdlib> // divmod

size_t max_i = 1000000;
size_t max_j = 10;
size_t max_k = 10;

size_t N = max_i * max_j * max_k; // beware of overflow

for( size_t m=0 ; m<N ; ++m )
{
    div_t q = div( m, max_k );
    size_t k = q.rem;

    q = div( q.quot, max_j );
    size_t j = q.rem;

    q = div( q.quot, max_i );
    size_t i = q.rem;

    // Now i, j, k are set. Do as thou shall.
}

答案 2 :(得分:0)

在您的情况下,您可以通过存储最少量的元数据来轻松地解决这个问题。

由于你有两个相对较小的向量,因此可以存储所有j / k组合的起始位置。

size_t max_i = 1000000;
size_t max_j = 10;
size_t max_k = 10;

你想重组你的矢量来存储[k] [j] [i]。如果将100个可能的j / k组合存储在std :: map中,则可以通过查找小于矢量地址的最大地址来找到j / k值。从那里,你计算以字节为单位的偏移量,然后除以结构的大小来计算出i。

如果max_j和max_k变大,它就变得不那么实用了。