1

今天我遇到了一个问题,即访问向量元素会随着向量的大小而变慢。由于这不是我的代码,我无法发布它,所以请多多包涵。我将尝试尽可能详细地描述它。

代码的功能如下: 1. Dataset 类,采用.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];

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

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

在循环之前,它运行得非常快,但我很快就用完了内存。

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

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

4

4 回答 4

5

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

让你getDatavector()返回std::Vector<Image<unsigned short> >&std::Vector<Image<unsigned short> > const&不返回std::Vector<Image<unsigned short> >

于 2012-11-14T21:59:02.837 回答
5

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

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

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

如果您可以修改Dataset类,请将函数更改为

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

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

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

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

于 2012-11-14T22:03:02.790 回答
2

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

如果较早的 C++11 和 getDataVector 返回一个向量,则可能必须复制它。如果您使用的是 C++11,则可以将其移动到返回变量中而无需复制

这可能是你减速的根源。

访问向量的元素是一个常数时间操作。

于 2012-11-14T21:57:18.653 回答
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;
    }

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

于 2012-11-14T22:18:14.443 回答