scalanlp/breeze — pull request #166 by stucchio (2014-03-04 05:52:12+00:00)
Title: Created unsafeUpdate, unsafeValueAt for DenseVector. 

These can significantly improve performance, though of course at the cost of safety.

In terms of performance, consider the following implementation of Horner's algorithm for applying a polynomial to a dense vector (part of my incomplete polynomial branch):

def apply(k: PolyDenseUFuncWrapper, v: DenseVector[Double]) = {
val coeffs: Array[Double] = k.p.coeffs
var i = coeffs.length - 1
var result = DenseVector.fill[Double](v.size, coeffs(i))
while (i > 0) {
i -= 1
val c = coeffs(i)
cfor(0)(j => j < result.size, j => j+1)( j => {
result.unsafeUpdate(j, result.unsafeValueAt(j)*v.unsafeValueAt(j)+c)
// result.update(j, result.valueAt(j)*v.valueAt(j)+c)
})
}
result
}

Consider the benchmark which runs the above code:

cfor(0)(j => j < 100, j => j+1)(j => {
p(x)
})

Here, `x` is a `DenseVector` with size 30 million. The version using `unsafe` functions takes 26-27 seconds to run, the safe version takes 32-35 seconds. That's a speedup worth exploiting, in my opinion.

Tangentially, building a specialized version of `DenseVector` specialized to the case where `stride=1` can also yield a speedup.