2

いくつかのコードをScalaに変換しています。これは、非常に大量のデータを含む内部ループにあるコードであるため、高速である必要があり、ハッシュテーブルでキーを検索して確率を計算する必要があります。キーが見つかったかどうかによって、異なることを行う必要があります。「標準」イディオムを使用すると、コードは次のようになります。

counts.get(word) match {
  case None => {
    WordDist.overall_word_probs.get(word) match {
      case None => (unseen_mass*WordDist.globally_unseen_word_prob
                    / WordDist.num_unseen_word_types)
      case Some(owprob) => unseen_mass * owprob / overall_unseen_mass
    }
  }
  case Some(wordcount) => wordcount.toDouble/total_tokens*(1.0 - unseen_mass)
}

しかし、これらすべての一時的なSome()オブジェクトが作成されてからガベージコレクションされるため、この種のコードが非常に遅くなるのではないかと心配しています。Scala2eの本は、スマートJVMがこれらを「最適化」して、コードが効率的に正しいことを行うようにすると主張していますが、これは実際にSunのJVMを使用して発生しますか?誰か知ってる?

4

2 に答える 2

1

はい、Someオブジェクトが作成されます (Noneはシングルトンです)。もちろん、JVM がそれを無視しない限り、それは、JVM がコードがそれほど多く呼び出されたと考えるかどうかなど、多くの要因に依存します。

とにかく、そのコードは実際には標準的なイディオムではありません。それについてのミームさえあります: ある経験豊富な Scala 開発者がこのようなコードを書いたことがあります。

とにかく、ここに私がそれを書き直す方法があります:

( counts 
  get word
  map (_.toDouble / total_tokens * (1.0 - unseen_mass))
  getOrElse (
    WordDist.overall_word_probs
    get word
    map (unseen_mass * _ / overall_unseen_mass)
    getOrElse (unseen_mass * WordDist.globally_unseen_word_prob
                / WordDist.num_unseen_word_types)
  )
)

その後、これをリファクタリングできます。両方のgetOrElseパラメーターは、適切な名前の別のメソッドに分割できます。入力なしで値を返すだけなので、かなり高速です。

ここで、 と の 2 つのメソッドだけを呼び出しOptionます。実装の始まりは次のとおりです。mapgetOrElse

@inline final def map
@inline final def getOrElse

パラメータgetOrElseは名前で渡されるため、無名関数の作成が必要になります。もちろん、パラメータ tomapも関数です。それ以外は、これらのメソッドがインライン化される可能性はかなり高いです。

それで、これがリファクタリングされたコードですが、適切な名前を付けるのに十分な知識はありません.

def knownWordsFrequency = counts get word map computeKnownFrequency
def computeKnownFrenquency = 
  (_: Int).toDouble / total_tokens * (1.0 - unseen_mass)

def probableWordsFrequency = (
  WordDist.overall_word_probs 
  get word 
  map computeProbableFrequency
)
def computeProbableFrequency = unseen_mass * (_: Double) / overall_unseen_mass

def unknownFrequency = (unseen_mass * WordDist.globally_unseen_word_prob
  / WordDist.num_unseen_word_types)

def estimatedWordsFrequency = probablyWordsFrequency getOrElse unknownFrequency

knownWordsFrequency getOrElse estimatedWordsFrequency
于 2011-10-12T22:16:57.493 に答える