C ++:解除分配3d矢量

时间:2016-01-28 08:38:02

标签: c++ vector

对于3D医学图像的切片超像素创建,我创建了一个3d矢量 (std :: std :: vector of std :: vector of vector of DataStr对象)。随着图像的尺寸(~150 x 150 x 150)。 DataStr是一种结构,用于存储体素信息,例如指向同一3d矢量中其邻居的指针向量。使用此方法比使用邻域迭代器或KdTree最近邻搜索循环图像要快得多,因为此信息必须可用于slic算法的每次迭代。而且,相比之下,使用它非常方便。但是,当3d矢量用完范围时,3d矢量的重新分配需要大约4分钟。任何人都可以告诉我为什么会这样,我怎么能避免这种情况?谢谢!

编辑:

第一次在这里提问,感谢您的耐心: - )!

struct DataStr{
  std::vector<DataStr*> neighbors;
  float cmpVal;
  int association;
  cv::Mat index;
  float intensity;
  DataStr() :association{ -1 }, cmpVal{ std::numeric_limits<float>::max() }{}
};

上面是.hpp文件中的结构。下面定义和初始化dat

std::vector<std::vector<std::vector<DataStr>>> dat;
for (int i{ 0 }; i < imgDim[0]; ++i)
{
    dat.resize(imgDim[0]);
    for (int j{ 0 }; j < imgDim[1]; ++j)
    {
        dat[i].resize(imgDim[1]);
        for (int k{ 0 }; k < imgDim[2]; ++k)
        {
            dat[i][j].resize(imgDim[2], DataStr{});
        }
    }
}

imgDim是图像维度的3d数组。

 for (it_nImg.GoToBegin(), it_nMask.GoToBegin(), it_nCent.GoToBegin();    !it_nImg.IsAtEnd(); ++it_nImg, ++it_nMask, ++it_nCent)
{       
    auto  idx = it_nMask.GetIndex();
    DataStr* str = &dat[idx[0]][idx[1]][idx[2]];
    (*str).intensity = it_nImg.GetCenterPixel();
    (*str).index = (cv::Mat_<float>(1, 3) << idx[0], idx[1], idx[2]);

    for (int i = 0; i < it_nMask.Size(); ++i)
    {
        auto tmpIdx = it_nMask.GetIndex(i);
        (*str).neighbors.push_back(&dat[tmpIdx[0]][tmpIdx[1]][tmpIdx[2]]);
    }

}

it_n *是来自itk库的图像邻域迭代器,用于填充图像中每个体素的DataStr中的邻域向量。 it_nMask.Size()是所选邻域的大小。 it_n * .GetIndex()提供3d体素索引的3元素数组。非常感谢。

修改编辑:

如果我存储相邻体素的索引而不是指向它们的指针,则释放仅需0.5秒。这是因为指向DataStr的指针长度为8个字节,而我的机器上的int只有4个字节吗?

1 个答案:

答案 0 :(得分:0)

您提到性能问题在析构函数中。制作向量向量的向量会导致150 + 150 * 150分配和解除分配。如果您在分配时没有看到它,我怀疑它是因为它会因您的使用而摊销。

在你的情况下说

是否可以接受
std::vector<DataStr> dat;
int dat_size = imgDim[0] * imgDim[1] * imgDim[2];
dat.reserve(dat_size);
// No need to loop and initialize, the default constructor
// will do that for you.

然后在你的大循环中,替换这一行

DataStr* str = &dat[idx[0]][idx[1]][idx[2]];

这一个

DataStr& str = dat[dat_index(idx[0], idx[1], idx[2])];

(然后有一些细节,因为我使用的是引用而不是指针)。在这里,我已经定义了一个辅助函数,

inline int dat_index(int x, int y, int z) {
    return imgDim[0] * imgDim[1] * x + imgDim[0] * y + z;
}

可能会略有不同,具体取决于您如何考虑指数。