Golub-Kahan SVD algorithm for KMP tensors #499

Closed
grinisrit wants to merge 64 commits from dev into dev
Showing only changes of commit 38ed6dd995 - Show all commits

View File

@ -8,27 +8,134 @@ import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import org.ejml.UtilEjml.assertTrue
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.diagonalEmbedding
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.dot
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.eq
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.svdGolubKahan
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.transpose
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.svdPowerMethod
@State(Scope.Benchmark)
class SVDBenchmark {
companion object {
val tensor = DoubleTensorAlgebra.randomNormal(intArrayOf(10, 10, 10), 0)
val tensorSmall = DoubleTensorAlgebra.randomNormal(intArrayOf(5, 5), 0)
val tensorMedium = DoubleTensorAlgebra.randomNormal(intArrayOf(10, 10), 0)
val tensorLarge = DoubleTensorAlgebra.randomNormal(intArrayOf(50, 50), 0)
val tensorVeryLarge = DoubleTensorAlgebra.randomNormal(intArrayOf(100, 100), 0)
val epsilon = 1e-9
}
@Benchmark
fun svdPowerMethod(blackhole: Blackhole) {
fun svdPowerMethodSmall(blackhole: Blackhole) {
val svd = tensorSmall.svdPowerMethod()
val tensorSVD = svd.first
.dot(
diagonalEmbedding(svd.second)
.dot(svd.third.transpose())
)
assertTrue(tensorSVD.eq(tensorSmall, epsilon))
blackhole.consume(
tensor.svdPowerMethod()
tensorSmall.svdPowerMethod()
)
}
@Benchmark
fun svdGolubKahan(blackhole: Blackhole) {
fun svdPowerMethodMedium(blackhole: Blackhole) {
val svd = tensorMedium.svdPowerMethod()
val tensorSVD = svd.first
.dot(
diagonalEmbedding(svd.second)
.dot(svd.third.transpose())
)
assertTrue(tensorSVD.eq(tensorMedium, epsilon))
blackhole.consume(
tensor.svdGolubKahan()
tensorMedium.svdPowerMethod()
)
}
@Benchmark
fun svdPowerMethodLarge(blackhole: Blackhole) {
val svd = tensorLarge.svdPowerMethod()
val tensorSVD = svd.first
.dot(
diagonalEmbedding(svd.second)
.dot(svd.third.transpose())
)
assertTrue(tensorSVD.eq(tensorLarge, epsilon))
blackhole.consume(
tensorLarge.svdPowerMethod()
)
}
@Benchmark
fun svdPowerMethodVeryLarge(blackhole: Blackhole) {
val svd = tensorVeryLarge.svdPowerMethod()
val tensorSVD = svd.first
.dot(
diagonalEmbedding(svd.second)
.dot(svd.third.transpose())
)
assertTrue(tensorSVD.eq(tensorVeryLarge, epsilon))
blackhole.consume(
tensorVeryLarge.svdPowerMethod()
)
}
@Benchmark
fun svdGolubKahanSmall(blackhole: Blackhole) {
val svd = tensorSmall.svdGolubKahan()
val tensorSVD = svd.first
.dot(
diagonalEmbedding(svd.second)
.dot(svd.third.transpose())
)
assertTrue(tensorSVD.eq(tensorSmall, epsilon))
blackhole.consume(
tensorSmall.svdGolubKahan()
)
}
@Benchmark
fun svdGolubKahanMedium(blackhole: Blackhole) {
val svd = tensorMedium.svdGolubKahan()
val tensorSVD = svd.first
.dot(
diagonalEmbedding(svd.second)
.dot(svd.third.transpose())
)
assertTrue(tensorSVD.eq(tensorMedium, epsilon))
blackhole.consume(
tensorMedium.svdGolubKahan()
)
}
@Benchmark
fun svdGolubKahanLarge(blackhole: Blackhole) {
val svd = tensorLarge.svdGolubKahan()
val tensorSVD = svd.first
.dot(
diagonalEmbedding(svd.second)
.dot(svd.third.transpose())
)
assertTrue(tensorSVD.eq(tensorLarge, epsilon))
blackhole.consume(
tensorLarge.svdGolubKahan()
)
}
@Benchmark
fun svdGolubKahanVeryLarge(blackhole: Blackhole) {
val svd = tensorVeryLarge.svdGolubKahan()
val tensorSVD = svd.first
.dot(
diagonalEmbedding(svd.second)
.dot(svd.third.transpose())
)
assertTrue(tensorSVD.eq(tensorVeryLarge, epsilon))
blackhole.consume(
tensorVeryLarge.svdGolubKahan()
)
}
}