diff options
3 files changed, 25 insertions, 12 deletions
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/IndexedTensor.java b/vespajlib/src/main/java/com/yahoo/tensor/IndexedTensor.java index 7c65b2a1fd2..e946f80eb97 100644 --- a/vespajlib/src/main/java/com/yahoo/tensor/IndexedTensor.java +++ b/vespajlib/src/main/java/com/yahoo/tensor/IndexedTensor.java @@ -28,6 +28,14 @@ public class IndexedTensor implements Tensor { this.type = type; this.firstDimension = firstDimension; } + + /** Construct an indexed tensor having a single dimension with the given values */ + public IndexedTensor(TensorType type, List<Object> values) { + if (type.dimensions().size() != 1 || ! type.dimensions().get(0).isIndexed()) + throw new IllegalArgumentException("Expected a single-dimensional indexed tensor but got " + type); + this.type = type; + this.firstDimension = new IndexedDimension(values); + } /** * Returns the value at the given indexes diff --git a/vespajlib/src/main/java/com/yahoo/tensor/functions/Join.java b/vespajlib/src/main/java/com/yahoo/tensor/functions/Join.java index ee3f9e13668..e439b273429 100644 --- a/vespajlib/src/main/java/com/yahoo/tensor/functions/Join.java +++ b/vespajlib/src/main/java/com/yahoo/tensor/functions/Join.java @@ -76,11 +76,11 @@ public class Join extends PrimitiveTensorFunction { } private Tensor indexedVectorJoin(IndexedTensor a, IndexedTensor b, TensorType type) { - IndexedTensor.Builder builder = new IndexedTensor.Builder(type); + ImmutableList.Builder<Object> builder = new ImmutableList.Builder<>(); int joinedLength = Math.min(a.length(0), b.length(0)); for (int i = 0; i < joinedLength; i++) - builder.set(combinator.applyAsDouble(a.get(i), b.get(i)), i); - return builder.build(); + builder.add(combinator.applyAsDouble(a.get(i), b.get(i))); + return new IndexedTensor(type, builder.build()); } /** When both tensors have the same dimensions, at most one cell matches a cell in the other tensor */ diff --git a/vespajlib/src/test/java/com/yahoo/tensor/TensorFunctionBenchmark.java b/vespajlib/src/test/java/com/yahoo/tensor/TensorFunctionBenchmark.java index 6c41037fe08..7c451faf8a5 100644 --- a/vespajlib/src/test/java/com/yahoo/tensor/TensorFunctionBenchmark.java +++ b/vespajlib/src/test/java/com/yahoo/tensor/TensorFunctionBenchmark.java @@ -1,6 +1,8 @@ package com.yahoo.tensor; +import com.yahoo.tensor.functions.Join; import com.yahoo.tensor.functions.Reduce; +import com.yahoo.tensor.functions.TensorFunction; import java.util.*; @@ -15,7 +17,7 @@ public class TensorFunctionBenchmark { public double benchmark(int iterations, List<Tensor> modelVectors, TensorType.Dimension.Type dimensionType) { Tensor queryVector = generateVectors(1, 300, dimensionType).get(0); - dotProduct(queryVector, modelVectors, 10); // warmup + dotProduct(queryVector, modelVectors, Math.max(iterations/10, 10)); // warmup long startTime = System.currentTimeMillis(); dotProduct(queryVector, modelVectors, iterations); long totalTime = System.currentTimeMillis() - startTime; @@ -31,6 +33,8 @@ public class TensorFunctionBenchmark { private double dotProduct(Tensor tensor, List<Tensor> tensors) { double largest = Double.MIN_VALUE; + // TODO: Build function before applying, support context + // TensorFunction dotProduct = new Reduce(new Join(), Reduce.Aggregator.max); for (Tensor tensorElement : tensors) { // tensors.size() = 1 for larger tensor Tensor result = tensor.join(tensorElement, (a, b) -> a * b).reduce(Reduce.Aggregator.sum, "x"); double dotProduct = result.reduce(Reduce.Aggregator.max).asDouble(); // for larger tensor @@ -103,22 +107,23 @@ public class TensorFunctionBenchmark { // Initial: 150 ms // - After adding type: 300 ms // - After sorting dimensions: 100 ms - // - After special-casing single space: 3.1 ms - time = new TensorFunctionBenchmark().benchmark(1000, generateVectors(100, 300, TensorType.Dimension.Type.mapped), TensorType.Dimension.Type.mapped); + // - After special-casing single space: 2.4 ms + time = new TensorFunctionBenchmark().benchmark(5000, generateVectors(100, 300, TensorType.Dimension.Type.mapped), TensorType.Dimension.Type.mapped); System.out.printf("Mapped vectors, time per join: %1$8.3f ms\n", time); - // Initial: 800 ms - time = new TensorFunctionBenchmark().benchmark(20, generateMatrix(100, 300, TensorType.Dimension.Type.mapped), TensorType.Dimension.Type.mapped); + // Initial: 760 ms + time = new TensorFunctionBenchmark().benchmark(10, generateMatrix(100, 300, TensorType.Dimension.Type.mapped), TensorType.Dimension.Type.mapped); System.out.printf("Mapped matrix, time per join: %1$8.3f ms\n", time); // ---------------- Indexed: // Initial: 718 ms // - After special casing join: 3.6 ms - // - After special-casing reduce: 0.8 ms - time = new TensorFunctionBenchmark().benchmark(1000, generateVectors(100, 300, TensorType.Dimension.Type.indexedUnbound),TensorType.Dimension.Type.indexedUnbound); + // - After special-casing reduce: 0.80 ms + // - After create IndexedTensor without builder: 0.41 ms + time = new TensorFunctionBenchmark().benchmark(5000, generateVectors(100, 300, TensorType.Dimension.Type.indexedUnbound),TensorType.Dimension.Type.indexedUnbound); System.out.printf("Indexed vectors, time per join: %1$8.3f ms\n", time); // Initial: 3500 ms - time = new TensorFunctionBenchmark().benchmark(10, generateMatrix(100, 300, TensorType.Dimension.Type.indexedUnbound), TensorType.Dimension.Type.indexedUnbound); - System.out.printf("Indexed matrix, time per join: %1$8.3f ms\n", time); + // time = new TensorFunctionBenchmark().benchmark(10, generateMatrix(100, 300, TensorType.Dimension.Type.indexedUnbound), TensorType.Dimension.Type.indexedUnbound); + // System.out.printf("Indexed matrix, time per join: %1$8.3f ms\n", time); } } |