4

このコード サンプルをより効率的にコーディングする他の方法があるかどうかを確認しようとしています。ここで、y は 1xM 行列 (たとえば 1x1000)、z は NxM 行列 (たとえば 5x1000) です。

mean(ones(N,1)*y.^3 .* z,2)

ones(N,1)*y.^3このコードは正常に動作しますが、N が大幅に増加すると無駄が多くなり、すべてが遅くなる可能性があるのではないかと心配しています。

考え?

4

1 に答える 1

5

それほど小さいマトリックスではそれほどひどいことではありません。このような問題で bsxfun を使用すると、多くの場合得られます。ここでは、行列が小さすぎて実際には何も得られません。

>> N = 5;M =1000;
>> y = rand(1,M);
>> z = rand(N,M);
>> mean(ones(N,1)*y.^3 .* z,2)
ans =
      0.12412
      0.11669
      0.12102
      0.11976
      0.12196

>> mean(bsxfun(@times,y.^3,z),2)
ans =
      0.12412
      0.11669
      0.12102
      0.11976
      0.12196

>> z*y.'.^3/M
ans =
      0.12412
      0.11669
      0.12102
      0.11976
      0.12196

ご覧のとおり、3 つのソリューションはすべて同じ結果を返します。すべてが等しく有効です。

所要時間を比較してみます。

>> timeit(@() mean(ones(N,1)*y.^3 .* z,2))
ans =
   0.00023018

>> timeit(@() mean(bsxfun(@times,y.^3,z),2))
ans =
   0.00026829

>> timeit(@() z*y.'.^3/M)
ans =
   0.00016594

おっしゃる通り、あまり稼げません。実際、bsxfun はまったく増加せず、さらに少し遅くなります。しかし、私が提示した 3 番目の形式に式を書き直せば、少し得をすることができます。多くはありませんが、少しです。

編集: N が大きい場合、タイミングが少し変わります。

>> N = 2000;M = 1000;
>> y = rand(1,M);
>> z = rand(N,M);
>> timeit(@() mean(ones(N,1)*y.^3 .* z,2))
ans =
     0.034664

>> timeit(@() mean(bsxfun(@times,y.^3,z),2))
ans =
     0.012234

>> timeit(@() z*y.'.^3/M)
ans =
    0.0017674

違いは、最初のソリューションが展開された y.^3 行列を明示的に作成することです。これは非効率的です。

bsxfun ソリューションは、expand y.^3 行列を明示的に形成しないため、優れています。しかし、それでも N x M の積行列が形成されます。したがって、このソリューションは依然として大量のメモリを取得して埋める必要があります。

行列とベクトルの乗算がすべての場合に最適である理由を理解する必要があります。大規模なマトリックスが形成されることはありません。* は単純な内積 (積の合計) であるため、より効率的である必要があります。次に、事後的に M で割って、目的の平均を作成します。

最後の小さな改善...

>> timeit(@() z*(y.*y.*y).'/M)
ans =
    0.0015793

これは、パワーopをわずかに上回ります。

そしてタイムイット?これは、Steve Eddins によって作成されたタイム コード フラグメント用の非常に便利なユーティリティである File Exchange に由来します。

于 2012-08-29T21:21:03.780 に答える