2

移動平均を計算するはずの関数から QVector を返そうとしています。私の質問は、関数をより効率的にする方法です。数学は問題ありませんが、QVector を返す際に何か間違ったことをしたのではないかと思っています。これが私がこれまでに持っているコードです:

QVector<double> moving_exponential_average(const QVector<double>& a, double lambda) {
        if(lambda <0 ) {
            lambda = 0;
        }
        if(lambda >1) {
            lambda = 1;
        }
        QVector<double> b;
        b.reserve(a.size());

        b.append(a[0]);
        double l_inv = 1-lambda;
        for(unsigned int i = 1; i < a.size(); ++i) {
            b.append(a[i]*lambda+l_inv*b[i-1]);
        }
        return b;
    }

デフォルト コンストラクターを使用して、QVector がデフォルト値を設定しないようにします。はるかに遅いサイズ変更で同じことを試しました。これを最適化する方法について何か提案はありますか?

よろしく

4

4 に答える 4

5

QVector の実装はそのデータ ( http://qt-project.org/doc/qt-5.0/qtcore/implicit-sharing.html#implicitly-shared ) を共有するため、何も問題はありません。

于 2014-01-26T17:08:25.200 に答える
3

「戻り」に最も時間がかかると主張しているため、問題は関数自体ではなく、戻り値が使用されるサイトにある可能性があります。

残念ながら、コードが時間を浪費する場所は次のとおりです。

  1. QVector毎回の割り当てで平均が呼び出されます。おそらく繰り返し呼び出されるため、毎回新しいベクトルを割り当てる必要はありません。

  2. QVector::operator[]isDetachedへの呼び出しごとにこの厄介な呼び出しが行われるため、単純な配列アクセスよりもオーバーヘッドが少し大きくなりますoperator[]

  3. QVector::append。を呼び出すだけでなくisDetached、長さもチェックして変更します。

値を返すことにはまったく問題がないことに注意してください。これは簡単な操作であり、ほとんど時間がかかりません。返品に関してはOKです-そして返品のみ。しかし、返された値をどのように使用するかを示していないため、そこで何か間違ったことをしている可能性があるかどうかはわかりません.

割り当てとオーバーヘッドの繰り返しを防ぐためoperator[]に、ベクトルを再利用できるように保持するクラスを使用し、ベクトルを直接使用する代わりにベクトルのデータへのポインターを使用できます。

これをさらに高速化するには、おそらく SIMD 組み込み関数を使用する必要があります。

class Averager {
  QVector<double> m_result;
  Q_DISABLE_COPY(Averager)
public:
  QVector<double> movingExponentialAverage(const QVector<double> & a, double lambda) {
    if (lambda < 0) lambda = 0; else if (lambda > 1) lambda = 1;
    m_result.resize(a.size());
    double * b = m_result.data();
    double lInv = 1-lambda;
    for(int i = 1; i < a.size(); ++i) {
      b[i] = a[i] * lambda + b[i-1] * l_inv;
    }
    return m_result;
  }
};

void test() {
  Averager avg; 
  QVector<double> src;
  while (true) {
    update(src);
    const QVector<double> & dst = avg.movingExponentialAverage(src, 0.2);
    ...
  } 
于 2014-01-27T08:48:39.990 に答える
2

QVector共有クラスです。コピーは一定の操作であり、非常に高速である必要があります。

于 2014-01-26T17:07:50.603 に答える