今天我遇到了一个问题,访问矢量元素的速度随着矢量的大小而减慢。由于这不是我的代码,我无法发布,所以请耐心等待。我将尝试尽可能详细地描述它。
代码的功能如下:
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())作为指针来访问内容。似乎没有什么能提高它的速度。
答案 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;
}
如果您必须拥有每张图片的副本,显然这不起作用。