減衰だと…っ!?

毎日G1GCのコードを読んでいて、もうそろそろ完全制覇か、と思ったところにワケワカなコードがでてきた。

void AbsSeq::add(double val) {
  if (_num == 0) {
    // if the sequence is empty, the davg is the same as the value
    _davg = val;
    // and the variance is 0
    _dvariance = 0.0;
  } else {
    // otherwise, calculate both
    _davg = (1.0 - _alpha) * val + _alpha * _davg;
    double diff = val - _davg;
    _dvariance = (1.0 - _alpha) * diff * diff + _alpha * _dvariance;
  }
}

この関数は何らかの値を列の中に突っ込むもので、その突っ込む値を _davg と _dvariance にゴニョゴニョやって計算しているらしい。
_davg は decaying average(減衰平均)の略で、 _dvariance は decaying variance(減衰分散)の略だ。
_alpha はデフォルトで0.7と設定されている。
 
減衰(decay)ってなんぞやと調べてみると以下のような意味らしい。

[名](スル)しだいに減っていくこと。

http://kotobank.jp/word/%E6%B8%9B%E8%A1%B0
何かの距離に応じて値が減ってしまうことなんかな、と想像。
 
コードをよく見ると以下のように減衰されている(?)ことに気づく。

_davg = 3割の現在の値(val) + 7割の前計算した値(_davg)
※ 現在の値(val)は3割しか反映されない(減衰してる)

前の計算結果に7割も影響されるわけだから、前計算結果から現在の値が遠く離れたとしても、求められる値はだいぶん減った値になるっぽい。
(何を言ってるんだ俺は…!)
 
頭で考えても本当かどうかわからなかったのでグラフにしてみる。

# /tmp/t.rb
abs = []
b = 0.0
c = 0.0
100.times do |i|
  a = sprintf("%.2f", rand).to_f
  b = a if i == 0
  b = (1.0 - 0.7) * a + 0.7 * b
  diff = a - b
  abs << a
  c = (1.0 - 0.7) * (diff * diff) + 0.7 * c
  puts "#{a},#{b},#{c}"
end
p (abs.inject(0.0){|r,i| r+=i }/abs.size)
ruby /tmp/t.rb /tmp/a.csv


Aがval、Bが_davg、Cが_dvariance。
振り幅が大きくてもBはそれ程変動してない。これが減衰とかなのか。
 
と、数学が苦手だし、頭がよくないので毎回こんな感じでカクカクと躓きながら読んでいます。
G1GC解説の公開までは時間がかかりそうなのが分かってもらえたでしょうか…。
 
あと、何かこれは正しい日本語の用語があったりするんでしょうか?
「減衰平均」とかそんな感じで説明してもいいもんなんですかね…。
何か知ってらっしゃる方は教えてくださると助かります。
 

追記

@さんに解説を書いてもらいました。
http://rednaxelafx.javaeye.com/blog/826678
なるほど。こういうことだったのか。