Scala
ScalaでのNumericの動作を教えてもらったのでベクトル計算のベンチマークをAO Benchでとってみた。
ソースはgithubに https://gist.github.com/1029695
イミュータブル
素直に数式を書けるように定義してみる。
case class Vec3d(x:Double, y:Double, z: Double) { def +(v: Vec3d) = Vec3d(x + v.x, y + v.y, z + v.z) def -(v: Vec3d) = Vec3d(x - v.x, y - v.y, z - v.z) } def ray_sphere_intersect(isect: Isect, ray: Ray, sphere: Sphere) { val rs = ray.org - sphere.center val B = rs * ray.dir val C = rs * rs - sphere.radius * sphere.radius val D = B * B - C … }
$ scala -J-server jp.peppermint.vec.immutable.App List(9494, 9508, 9448, 9471, 9445) 9471.0
Java版(http://leonardo-m.livejournal.com/79346.html)の半分くらいの実行速度。
ミュータブル
2オペランドのような感じで中間オブジェクトの生成を抑えてみる。
class Vec3d(var x:Double = 0, var y:Double = 0, var z: Double = 0) { def this(v: Vec3d) = this(v.x, v.y, v.z) def +=(v: Vec3d) { x += v.x y += v.y z += v.z } ... } def ray_sphere_intersect(isect: Isect, ray: Ray, sphere: Sphere) { val rs = new Vec3d(ray.org) rs -= sphere.center val B = rs * ray.dir val C = rs * rs - sphere.radius * sphere.radius val D = B * B - C ...
$ scala -J-server jp.peppermint.vec.mutable.App List(3846, 3853, 3854, 3833, 3840) 3846.3333333333335
ほぼJava版と同じ。
イミュータブル ジェネリック版
ベクトルの要素を型パラメータで変えられるように。
case class Vec3[T](x: T, y: T, z: T)(implicit num: Fractional[T], real: Real[T]) { import num._ import real._ def +(v: Vec3[T]) = Vec3[T](x + v.x, y + v.y, z + v.z) def -(v: Vec3[T]) = Vec3[T](x - v.x, y - v.y, z - v.z)
$ scala -J-server jp.peppermint.vec.immutable.gen.App List(20906, 20901, 20805, 21094, 21006) 20937.666666666668
だいぶ遅い。ボクシング・暗黙の型変換でのラッパクラス生成・interface経由のメソッドコールあたりが原因かな?
追記
64bit JVMでは特性が違うようなので後で調査