std::vector.resize的性能问题

wingfiring 2005-09-15 11:26:12
我的环境:.net 2003 的stl。
代码如下:vector<char> v;
我为了快速的load数据到v当中,于是:
v.reserve(1024 * 1024 * 100);
v.resize(1024 * 1024 * 100);
可是,resize操作需要做构造操作,在我的机器上,上一句大概需要150ms,太慢了。
但是我需要resize之后,我才可以安全的通过&v[0]往里面塞大量数据。

因为item类型是char,根本不需要构造,于是,我重载了allocator:
struct myAlloc : public allocator<char>
{
//覆盖construct和destory,函数体为空,期望inline优化掉。
};
vector<char, myAlloc> v;
编译行参数/DNDEBUG /GX /O2 /Og /Ob2
结果平均只快了10ms左右。我不知道为什么,预想的构造循环没有被优化掉,也许,是vc7.1的stl代码的问题?我很郁闷!
理论上,我reserve之后,只要修改v内部的size数据就可以了,但那个纯属hack,而且不可移植。
有没有办法快速的resize呢?或者,达到快速向vector里面放数据的目的呢?
...全文
672 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
__________________ 2005-09-21
  • 打赏
  • 举报
回复
vc的stl中的内存分配器只中是一个new的壳。你可以看一下它的源码。里面就一个new。你可以测一下使用stl的内存分配器和使用new的速度情况。是一样速度的。
如果想要一个buffer。自己做一个不就完了。
wingfiring 2005-09-20
  • 打赏
  • 举报
回复
居然是用fill。。。。无语
Jinhao 2005-09-20
  • 打赏
  • 举报
回复
p = allocator.allocate(size_t n);
for (i = 0; i < n; i++)
allocator.construct(p + i, var);

实际上resize是insert操作,在insert n个元素的时候是用的类似fill_n的操作,而不是用construct挨个构造。所以对construct在怎么优化,也不会得到太多的效果,因为在fill_n里往这n个字节的内存里写数据,事实上这个操作完全没意义,因为,在这里,char的构造函数是trivial的。

STL的实现不是针对某一特例来特别撰写的代码,所以,在这里,它就显得有那么多的代码是效率的杀手
wingfiring 2005-09-19
  • 打赏
  • 举报
回复
不知道这样用vector是不是想利用STL的算法?如果只是当作一个容器来用的话,而且是定长,好象这样没必要吧
----------------------
确实,我是想用stl算法。但是这个容器并不是定长的。
所以,我现在这能是这样:
char * v = new char[n];
...

delete[] v;
我已经很久不这样赤裸裸的用native指针了。这样的代码很糟糕,去写一个wrapper类
固然是一个正确的做法,但是,如果能在stl中找到合适的做法,我是坚决反对自己打造轮子的。
wingfiring 2005-09-19
  • 打赏
  • 举报
回复
我没有比较两者的源代码,我推测的resize 扩展时的源代码应该大致如下:
p = allocator.allocate(size_t n);
for (i = 0; i < n; i++)
allocator.construct(p + i, var);
其它判断、分析部分的处理时间应该都是个常数,只有这部分和n有关。
很显然,如果我把construct inline了,而construct又是空的,那么这个for循环完全是可以优化掉的。
我甚至把pointer改成了const pointer,希望可以提示编译器。
然而,vc7.1有能力优化空的for循环,这一点我是验证过的。那么,为什么resize效率这么低?
一种可能,是“优化空的for循环”的能力还不能运用到template上。另一个可能,那就是vc7.1的那个resize代码太烂。无论是修改stl源代码,还是换stl,还是换编译器,显然都是一个比较难以付出的代价。
所以,我很郁闷。。。。
Jinhao 2005-09-17
  • 打赏
  • 举报
回复
v.reserve(1024 * 1024 * 100);
v.resize(1024 * 1024 * 100);

就是这段代码SGI STL比VC的那个W什么STL来着快了2倍多。看来SGI的allocator的确要NB得多
Jinhao 2005-09-17
  • 打赏
  • 举报
回复
莫办法了,因为在resize的时候,根本和construct打交道,新的元素都是uninitialize地被初始化

不知道这样用vector是不是想利用STL的算法?如果只是当作一个容器来用的话,而且是定长,好象这样没必要吧
xiao_xiao_zi 2005-09-15
  • 打赏
  • 举报
回复
用Release编译比较看看
Debug好象不inline??
期待牛人~~
wingfiring 2005-09-15
  • 打赏
  • 举报
回复
但是,我覆盖了construct啊。
void
allocator<T>::construct(pointer p, const T& val)
{
//什么也不写
}

inline
void
allocator<T>::destroy(pointer p )
{
//什么也不写
}
dhy311 2005-09-15
  • 打赏
  • 举报
回复
vector默认的内存分配是这样写construct的
template<class T>
inline
void
allocator<T>::construct(pointer p, const T& val)
{
::new((void*)p) T(val);
}
template<class T>
inline
void
allocator<T>::destroy(pointer p )
{
p->~T();
}
dhy311 2005-09-15
  • 打赏
  • 举报
回复
覆盖construct和destory,我想跟这个有关西,
因为vector 通过allocator声请 n×sizeof(class T)的时候,会调用T的构造函数,会在destory的时候会调用响应的析构函数,其实大部分时间是浪费在这里,
我想多出来的时间是在这里。

24,855

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧