访问std :: vector元素会随着矢量大小而减慢

时间:2012-11-14 21:54:17

标签: c++ performance stl stdvector

今天我遇到了一个问题,访问矢量元素的速度随着矢量的大小而减慢。由于这不是我的代码,我无法发布,所以请耐心等待。我将尝试尽可能详细地描述它。

代码的功能如下: 1.数据集类,采用.txt文件,其中包含文件名。这些指向需要加载的标准png图像。这是由Image<T>类完成的。图像以Image<unsigned char>加载并推回std::Vector。 2.完成数据加载后。我可以访问我的数据集中的向量,以便使用它。所以它看起来像这样:

Dataset d;
d.init("filenames_list.txt"); //Loads the images
for(int i=0; i< d.getDatavector().size(); i++){
  Image<unsigned char> current = d.getDatavector()[i];
  //Do work on current image here.
}

这里getDatavector()将返回std::Vector<Image<unsigned char> >。对于宽度,高度和通道数,图像保持三个整数,并且还包含指向交错数据的Boost共享指针。

对于小型测试,我有一个包含大约150张图像的文件列表。使用此程序运行程序工作正常,速度测量告诉我

Image<unsigned char> current = d.getDatavector()[i];

需要大约10毫秒才能完成。但是,如果我想处理1500张图像的完整数据集,则上述行需要大约500毫秒才能完成。我试图做很多不同的事来解决它,但我受到代码的一般结构和内存的限制。因为如果我执行以下操作:

const std::Vector<Image<unsigned char> > data = d.getDatavector();

在循环之前,它运行得非常快,但我很快就会耗尽内存。

我知道我的问题描述有些模糊,我不希望得到确切的解决方案,但我希望有一些关于在哪里寻找的提示。我搜索了类似的问题,但人们似乎只关心向量与数组的一般速度。我的问题是,速度会随着矢量的长度而降低!如果有人看到这种问题,我们非常欢迎任何建议!

到目前为止,我尝试使用std :: vector :: iterator或使用(d.getDatavector(。。data())作为指针来访问内容。似乎没有什么能提高它的速度。

4 个答案:

答案 0 :(得分:5)

原因是你在循环中按值返回向量。

让您的getDatavector()返回std::Vector<Image<unsigned short> >&std::Vector<Image<unsigned short> > const&而不是std::Vector<Image<unsigned short> >

答案 1 :(得分:5)

getDataVector()的签名是什么样的?是吗

std::vector<Image<unsigned char>> getDataVector();

如果是这样,该函数将返回vector的值,每次写d.getDatavector()[i] vector的副本时,都会复制i元素超出vector,然后vector本身就会被销毁。

如果您可以修改Dataset类,请将功能更改为

std::vector<Image<unsigned char>> const& getDataVector();

现在每次调用函数时都不会复制。

如果您无法修改该类,请在进入循环之前制作单个副本,然后在循环中使用局部变量。

问题不可能是索引,因为std::vector的基础数据数组必须是连续的,因此访问 i th 元素就像将i添加到指示数据数组的起始地址并取消引用结果的指针一样简单。

答案 2 :(得分:2)

您使用的是C ++ 11还是早期的C ++?

如果早期的C ++ 11和getDataVector返回一个向量,则可能必须复制它。 如果你正在使用C ++ 11,它可以移动到没有复制的返回变量

可能是您放缓的原因。

访问向量的元素是一个恒定时间操作。

答案 3 :(得分:1)

正如已经提到的,问题的根源似乎在于getDatavector()返回向量的完整副本,解决方案是返回引用(或指针)。
您在Image<unsigned char> current = ...也遇到类似的问题,其中也会制作图像的副本 这些问题的一个解决方案是使用对图像的直接访问:

Image<unsigned char>* getImage(int idx)
{
 if (idx < _myVector.size())
 {
   return &_myVector[idx].Image;
 }
 return NULL;
}

编辑版本返回引用

    Image<unsigned char>& getImage(int idx)
    {
     if (idx < _myVector.size())
     {
       return _myVector[idx].Image;
     }
     // throw exception here;
    }

如果您必须拥有每张图片的副本,显然这不起作用。