0

std::vector<double>かなり頻繁に使用するルーチンを作成しました。実行速度はかなり遅く、AQTimeは、私がベクトルの山を構築していることを示唆しているようですが、なぜそうなるのかわかりません。状況によっては、サンプルの実行が10回繰り返されます。各反復は、約400ポイントの3つのc配列をベクトルにコピーし、出力用に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>、double *、std ::allocator>3.65秒および115731ヒット

std ::_Construct1.69秒と46450637ヒット

std :: _ Vector_const_iterator> :: 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万回以上呼び出されます。

私は明らかに、これらすべてのオブジェクトを作成させるために何か間違ったことをしています。誰かが私のエラーを見ることができますか?

4

2 に答える 2

2

これは、関数の引数を値で渡すためです。aが値で渡されるたび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...

なぜなら、あなたの使用法のために、これらのベクトルの別々のコピーを実際に作成する必要はなかったからです。

于 2012-07-10T03:21:34.313 に答える
1

ベクトルを渡して返す方法(「値による」)が原因で、ベクトルをいくつかの場所で非効率的に(「深く」)コピーしています。たとえば、VValue()メソッドは、メソッドと同様に、そのベクトルパラメータのコピーを作成します。この場合RatioPoint()、両方のベクトル引数が(不必要に)全体としてコピーされます。const vector<double>&代わりに、ベクトル引数を(つまり、のように「参照によって」)として渡したいと思うかもしれませんSaveVector()

また、GetVector()メソッドはベクトルのコピーを返す場合がありますが、コンパイラーがそれを最適化すればおそらく回避されます(walriiがここでの私の元の誤った投稿への返信で指摘したように)。C ++ -11を使用している場合は、可動を返すことができます(walriiも指摘しているように)。これらに失敗すると、解決策は少しトリッキーになります。ヒープにベクトルを割り当てて、共有ポインターまたは自動ポインターを返すことを検討してください。

于 2012-07-10T03:20:03.253 に答える