2012-11-14 58 views
1

今天,我遇到了访问向量元素随矢量大小变慢的问题。由于这不是我的代码,我无法发布,所以请耐心等待。我会尽可能详细地描述它。访问std ::向量元素减慢向量大小

代码的功能如下: 1. a数据集类,需要一个.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共享指针。

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

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

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

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

循环之前

,它的运行速度非常快,但我很快就用完了内存。

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

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

+0

1)你在哪里开始/停止计时器? 2)你是否想要包含内存分配时间? 3)你是在IDE中还是在IDE(命令行)之外运行它? – 2012-11-14 21:56:56

+2

'getDatavector'是否返回一个引用?或价值? –

+0

确实,这看起来很奇怪,Image数据类型非常小,并且唯一的大部分是由智能指针携带的。 – didierc

回答

5

什么的getDataVector()样子的签名?难道

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

如果是这样,该函数返回你写d.getDatavector()[i]vector的一份拷贝每次vector的价值,并且,该i元素被复制出来的vector的,然后vector本身销毁。

如果你可以修改Dataset类变化的功能

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

现在副本不会进行每次函数被调用的时间。

如果您无法修改该类,请在之前将单个副本输入到循环中,然后使用循环内的局部变量。

这是不可能的,因为std::vector的底层数据阵列需要是连续的,因此访问元件是如添加i指针标记的起始地址一样简单的问题是,索引的数据数组并取消引用结果。

+0

非常感谢大家的帮助!这实际上解决了我的问题。我选择接受这个答案,因为它是最精细的。这实际上将加载时间从15分钟缩短到了10秒钟!特别是循环头文件中额外的d.getDataVector()。size()增加了额外的时间。传递一个const引用而不是复制对象是完美的解决方案,我不需要改变任何东西,除了添加const并且不会破坏通用管道:) – Pandoro

2

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

如果更早的C++ 11和getDataVector返回一个向量,那么它可能必须被复制。 如果您使用的是C++ 11,那么它可以被移动到返回变量中,而不是复制

这可能是您的减速源。

访问矢量的元素是一个常量操作。

+0

+1。我马上认为这个问题是关于它的慢点,而不是每个元素的访问。 – 2012-11-14 22:03:21

+0

但是,如果您移动'vector','Dataset'类将不会留下它的有效副本。这可能是不可取的。 – Praetorian

5

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

让您getDatavector()返回一个std::Vector<Image<unsigned short> >&std::Vector<Image<unsigned short> > const&std::Vector<Image<unsigned short> >

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

显然,如果你必须有这将无法工作每个图像的副本。