我编写了一个使用std::vector<double>
的例程。它的运行速度相当缓慢,AQTime似乎意味着我正在构建矢量山,但我不确定为什么会这样。对于某些上下文,我的示例运行迭代10次。每次迭代将3个约400个点的数组复制到矢量中,并创建3个新的相同大小的矢量用于输出。每个输出点可能是从2个输入向量求和最多20个点的结果,这可以解决10 * 400 * 3 * 2 * 20 = 480,000个解引用的最坏情况。令人遗憾的是,探查器指示某些std ::方法被称为4600万次。我怀疑我做错了什么!
一些代码:
vector<double>gdbChannel::GetVector() {
if (fHaveDoubleData & (fLength > 0)) {
double * pD = getDoublePointer();
vector<double>v(pD, pD + fLength);
return v;
} else {
throw(Exception("attempt to retrieve vector on empty line")); ;
}
}
void gdbChannel::SaveVector(GX_HANDLE _hLine, const vector<double> & V) {
if (hLine != _hLine) {
GetLine(_hLine, V.size(), true);
}
GX_DOUBLE * pData = getDoublePointer();
memcpy(pData, &V[0], V.size()*sizeof(V[0]));
ReplaceData();
}
///This routine gets called 10 times
bool SpecRatio::DoWork(GX_HANDLE_PTR pLine) {
if (!(hKin.GetLine(*pLine, true) && hUin.GetLine(*pLine, true) && hTHin.GetLine(*pLine, true))) {
return true;
}
vector<double>vK = hKin.GetVector();
vector<double>vU = hUin.GetVector();
vector<double>vTh = hTHin.GetVector();
if ((vK.size() == 0) || (vU.size() == 0) || (vTh.size() == 0)) {
return true;
}
///TODO: confirm all vectors the same lenghth
len = vK.size();
vUK.clear(); // these 3 vectors are declared as private class members
vUTh.clear();
vThK.clear();
vUK.reserve(len);
vUTh.reserve(len);
vThK.reserve(len);
// TODO: ensure everything is same fidincr, fidstart and length
for (int i = 0; i < len; i++) {
if (vK.at(i) < MinK) {
vUK.push_back(rDUMMY);
vUTh.push_back(rDUMMY);
vThK.push_back(rDUMMY);
} else {
vUK.push_back(RatioPoint(vU, vK, i, UMin, KMin));
vUTh.push_back(RatioPoint(vU, vTh, i, UMin, ThMin));
vThK.push_back(RatioPoint(vTh, vK, i, ThMin, KMin));
}
}
hUKout.setFidParams(hKin);
hUKout.SaveVector(*pLine, vUK);
hUTHout.setFidParams(hKin);
hUTHout.SaveVector(*pLine, vUTh);
hTHKout.setFidParams(hKin);
hTHKout.SaveVector(*pLine, vThK);
return TestError();
}
double SpecRatio::VValue(vector<double>V, int Index) {
double result;
if ((Index < 0) || (Index >= len)) {
result = 0;
} else {
try {
result = V.at(Index);
if (OasisUtils::isDummy(result)) {
result = 0;
}
}
catch (out_of_range) {
result = 0;
}
}
return result;
}
double SpecRatio::RatioPoint(vector<double>Num, vector<double>Denom, int Index, double NumMin, double DenomMin) {
double num = VValue(Num, Index);
double denom = VValue(Denom, Index);
int s = 0;
// Search equalled 10 in this case
while (((num < NumMin) || (denom < DenomMin)) && (s < Search)) {
num += VValue(Num, Index - s) + VValue(Num, Index + s);
denom += VValue(Denom, Index - s) + VValue(Denom, Index + s);
s++;
}
if ((num < NumMin) || (denom < DenomMin)) {
return rDUMMY;
} else {
return num / denom;
}
}
顶级AQTime违规者是:
std :: _ Uninit_copy&gt ;, double *,std :: allocator&gt; 3.65秒 和115731点击
std :: _ Construct 1.69 secs和46450637 Hits
std :: _ Vector_const_iterator&gt; :: operator != 1.66秒和46566395点击等等......
std::allocator<double>::construct
,
operator new
,
std::_Vector_const_iterator<double, std::allocator<double> >::operator ++
,std::_Vector_const_iterator<double, std::allocator<double> >::operator *
std::_Vector_const_iterator<double, std::allocator<double> >::operator ==
每次被召唤超过4600万次。
我显然做错了导致所有这些对象被创建。任何人都可以看到我的错误吗?
答案 0 :(得分:2)
这是因为您按值传递函数参数。每次按std::vector
传递值时,都必须制作完整的矢量副本。
更改这些:
double SpecRatio::VValue(vector<double>V, int Index) {
double SpecRatio::RatioPoint(vector<double>Num, vector<double>Denom...
要:
double SpecRatio::VValue(const vector<double> &V, int Index)
double SpecRatio::RatioPoint(const vector<double> &Num, const vector<double> &Denom...
因为您的使用,您实际上从未需要制作这些矢量的单独副本。
答案 1 :(得分:1)
由于您传递它们的方式并将它们返回(&#34;按值&#34;),您在几个地方复制矢量效率低下(&#34;深度&#34;)。例如,您的VValue()
方法正在复制其向量参数,就像您的RatioPoint()
方法一样,其中两个向量参数都被(不必要地)完整地复制。相反,您可能希望将矢量参数作为const vector<double>&
传递(即&#34;通过引用&#34;,就像在SaveVector()
中一样)。
此外,您的GetVector()方法可能会返回该向量的副本,但如果编译器对其进行优化,则可能会避免这种情况(正如walrii在回答我原来的错误帖子时指出的那样)。如果您使用的是C ++ - 11,则可以返回一个可移动的(如同walrii也指出)。如果失败了,解决方案有点棘手 - 你可以考虑在堆上分配向量并返回一个共享或自动指针。