You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2017/08/01 09:27:08 UTC

[23/50] [abbrv] ignite git commit: IGNITE-5278: BLAS implemented.

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/test/java/org/apache/ignite/ml/math/BlasTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/BlasTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/BlasTest.java
new file mode 100644
index 0000000..00bce47
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/BlasTest.java
@@ -0,0 +1,357 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math;
+
+import java.util.function.BiPredicate;
+import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.apache.ignite.ml.math.impls.matrix.SparseLocalOnHeapMatrix;
+import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
+import org.apache.ignite.ml.math.impls.vector.SparseLocalVector;
+import org.apache.ignite.ml.math.util.MatrixUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+/** Tests for BLAS operations (all operations are only available for local matrices and vectors). */
+public class BlasTest {
+    /** Test 'axpy' operation for two array-based vectors. */
+    @Test
+    public void testAxpyArrayArray() {
+        Vector y = new DenseLocalOnHeapVector(new double[] {1.0, 2.0});
+        double a = 2.0;
+        Vector x = new DenseLocalOnHeapVector(new double[] {1.0, 2.0});
+
+        Vector exp = x.times(a).plus(y);
+        Blas.axpy(a, x, y);
+
+        Assert.assertEquals(y, exp);
+    }
+
+    /** Test 'axpy' operation for sparse vector and array-based vector. */
+    @Test
+    public void testAxpySparseArray() {
+        DenseLocalOnHeapVector y = new DenseLocalOnHeapVector(new double[] {1.0, 2.0});
+        double a = 2.0;
+        SparseLocalVector x = sparseFromArray(new double[] {1.0, 2.0});
+
+        SparseLocalVector exp = (SparseLocalVector)x.times(a).plus(y);
+        Blas.axpy(a, x, y);
+
+        Assert.assertTrue(elementsEqual(exp, y));
+    }
+
+    /** Test 'dot' operation. */
+    @Test
+    public void testDot() {
+        DenseLocalOnHeapVector v1 = new DenseLocalOnHeapVector(new double[] {1.0, 1.0});
+        DenseLocalOnHeapVector v2 = new DenseLocalOnHeapVector(new double[] {2.0, 2.0});
+
+        Assert.assertEquals(Blas.dot(v1, v2), v1.dot(v2), 0.0);
+    }
+
+    /** Test 'scal' operation for dense matrix. */
+    @Test
+    public void testScalDense() {
+        double[] data = new double[] {1.0, 1.0};
+        double alpha = 2.0;
+
+        DenseLocalOnHeapVector v = new DenseLocalOnHeapVector(data);
+        Vector exp = new DenseLocalOnHeapVector(data, true).times(alpha);
+        Blas.scal(alpha, v);
+
+        Assert.assertEquals(v, exp);
+    }
+
+    /** Test 'scal' operation for sparse matrix. */
+    @Test
+    public void testScalSparse() {
+        double[] data = new double[] {1.0, 1.0};
+        double alpha = 2.0;
+
+        SparseLocalVector v = sparseFromArray(data);
+        Vector exp = sparseFromArray(data).times(alpha);
+
+        Blas.scal(alpha, v);
+
+        Assert.assertEquals(v, exp);
+    }
+
+    /** Test 'spr' operation for dense vector v and dense matrix A. */
+    @Test
+    public void testSprDenseDense() {
+        double alpha = 3.0;
+
+        DenseLocalOnHeapVector v = new DenseLocalOnHeapVector(new double[] {1.0, 2.0});
+        DenseLocalOnHeapVector u = new DenseLocalOnHeapVector(new double[] {3.0, 13.0, 20.0, 0.0});
+
+        // m is alpha * v * v^t
+        DenseLocalOnHeapMatrix m = (DenseLocalOnHeapMatrix)new DenseLocalOnHeapMatrix(new double[][] {{1.0, 0.0},
+            {2.0, 4.0}}, StorageConstants.COLUMN_STORAGE_MODE).times(alpha);
+        DenseLocalOnHeapMatrix a = new DenseLocalOnHeapMatrix(new double[][] {{3.0, 0.0}, {13.0, 20.0}},
+            StorageConstants.COLUMN_STORAGE_MODE);
+
+        //m := alpha * v * v.t + A
+        Blas.spr(alpha, v, u);
+
+        DenseLocalOnHeapMatrix mu = fromVector(u, a.rowSize(), StorageConstants.COLUMN_STORAGE_MODE, (i, j) -> i >= j);
+        Assert.assertEquals(m.plus(a), mu);
+    }
+
+    /** Test 'spr' operation for sparse vector v (sparse in representation, dense in fact) and dense matrix A. */
+    @Test
+    public void testSprSparseDense1() {
+        double alpha = 3.0;
+
+        SparseLocalVector v = sparseFromArray(new double[] {1.0, 2.0});
+        DenseLocalOnHeapVector u = new DenseLocalOnHeapVector(new double[] {3.0, 13.0, 20.0, 0.0});
+
+        DenseLocalOnHeapMatrix a = new DenseLocalOnHeapMatrix(new double[][] {{3.0, 0.0}, {13.0, 20.0}},
+            StorageConstants.COLUMN_STORAGE_MODE);
+        DenseLocalOnHeapMatrix exp = (DenseLocalOnHeapMatrix)new DenseLocalOnHeapMatrix(new double[][] {{1.0, 0.0},
+            {2.0, 4.0}}, StorageConstants.COLUMN_STORAGE_MODE).times(alpha).plus(a);
+
+        //m := alpha * v * v.t + A
+        Blas.spr(alpha, v, u);
+        DenseLocalOnHeapMatrix mu = fromVector(u, a.rowSize(), StorageConstants.COLUMN_STORAGE_MODE, (i, j) -> i >= j);
+        Assert.assertEquals(exp, mu);
+    }
+
+    /** Test 'spr' operation for sparse vector v (sparse in representation, sparse in fact) and dense matrix A. */
+    @Test
+    public void testSprSparseDense2() {
+        double alpha = 3.0;
+
+        SparseLocalVector v = new SparseLocalVector(2, StorageConstants.RANDOM_ACCESS_MODE);
+        v.set(0, 1);
+
+        DenseLocalOnHeapVector u = new DenseLocalOnHeapVector(new double[] {3.0, 13.0, 20.0, 0.0});
+
+        // m is alpha * v * v^t
+        DenseLocalOnHeapMatrix m = (DenseLocalOnHeapMatrix)new DenseLocalOnHeapMatrix(new double[][] {{1.0, 0.0},
+            {0.0, 0.0}}, StorageConstants.COLUMN_STORAGE_MODE).times(alpha);
+        DenseLocalOnHeapMatrix a = new DenseLocalOnHeapMatrix(new double[][] {{3.0, 0.0}, {13.0, 20.0}},
+            StorageConstants.COLUMN_STORAGE_MODE);
+
+        //m := alpha * v * v.t + A
+        Blas.spr(alpha, v, u);
+        DenseLocalOnHeapMatrix mu = fromVector(u, a.rowSize(), StorageConstants.COLUMN_STORAGE_MODE, (i, j) -> i >= j);
+        Assert.assertEquals(m.plus(a), mu);
+    }
+
+    /** Tests 'syr' operation for dense vector x and dense matrix A. */
+    @Test
+    public void testSyrDenseDense() {
+        double alpha = 2.0;
+        DenseLocalOnHeapVector x = new DenseLocalOnHeapVector(new double[] {1.0, 2.0});
+        DenseLocalOnHeapMatrix a = new DenseLocalOnHeapMatrix(new double[][] {{10.0, 20.0}, {20.0, 10.0}});
+
+        // alpha * x * x^T + A
+        DenseLocalOnHeapMatrix exp = (DenseLocalOnHeapMatrix)new DenseLocalOnHeapMatrix(new double[][] {{1.0, 2.0},
+            {2.0, 4.0}}).times(alpha).plus(a);
+
+        Blas.syr(alpha, x, a);
+
+        Assert.assertEquals(exp, a);
+    }
+
+    /** Tests 'gemm' operation for dense matrix A, dense matrix B and dense matrix C. */
+    @Test
+    public void testGemmDenseDenseDense() {
+        // C := alpha * A * B + beta * C
+        double alpha = 2.0;
+        DenseLocalOnHeapMatrix a = new DenseLocalOnHeapMatrix(new double[][] {{10.0, 11.0}, {0.0, 1.0}});
+        DenseLocalOnHeapMatrix b = new DenseLocalOnHeapMatrix(new double[][] {{1.0, 0.0}, {0.0, 1.0}});
+        double beta = 3.0;
+        DenseLocalOnHeapMatrix c = new DenseLocalOnHeapMatrix(new double[][] {{1.0, 2.0}, {2.0, 3.0}});
+
+        DenseLocalOnHeapMatrix exp = (DenseLocalOnHeapMatrix)a.times(b).times(alpha).plus(c.times(beta));
+
+        Blas.gemm(alpha, a, b, beta, c);
+        Assert.assertEquals(exp, c);
+    }
+
+    /** Tests 'gemm' operation for sparse matrix A, dense matrix B and dense matrix C. */
+    @Test
+    public void testGemmSparseDenseDense() {
+        // C := alpha * A * B + beta * C
+        double alpha = 2.0;
+        SparseLocalOnHeapMatrix a = sparseFromArray(new double[][] {{10.0, 11.0}, {0.0, 1.0}}, 2);
+        DenseLocalOnHeapMatrix b = new DenseLocalOnHeapMatrix(new double[][] {{1.0, 0.0}, {0.0, 1.0}});
+        double beta = 3.0;
+        DenseLocalOnHeapMatrix c = new DenseLocalOnHeapMatrix(new double[][] {{1.0, 2.0}, {2.0, 3.0}});
+
+        DenseLocalOnHeapMatrix exp = MatrixUtil.asDense((SparseLocalOnHeapMatrix)a.times(b).times(alpha).plus(c.times(beta)),
+            StorageConstants.ROW_STORAGE_MODE);
+
+        Blas.gemm(alpha, a, b, beta, c);
+
+        Assert.assertEquals(exp, c);
+    }
+
+    /** Tests 'gemv' operation for dense matrix A, dense vector x and dense vector y. */
+    @Test
+    public void testGemvSparseDenseDense() {
+        // y := alpha * A * x + beta * y
+        double alpha = 3.0;
+        SparseLocalOnHeapMatrix a = sparseFromArray(new double[][] {{10.0, 11.0}, {0.0, 1.0}}, 2);
+        DenseLocalOnHeapVector x = new DenseLocalOnHeapVector(new double[] {1.0, 2.0});
+        double beta = 2.0;
+        DenseLocalOnHeapVector y = new DenseLocalOnHeapVector(new double[] {3.0, 4.0});
+
+        DenseLocalOnHeapVector exp = (DenseLocalOnHeapVector)y.times(beta).plus(a.times(x).times(alpha));
+
+        Blas.gemv(alpha, a, x, beta, y);
+
+        Assert.assertEquals(exp, y);
+    }
+
+    /** Tests 'gemv' operation for dense matrix A, sparse vector x and dense vector y. */
+    @Test
+    public void testGemvDenseSparseDense() {
+        // y := alpha * A * x + beta * y
+        double alpha = 3.0;
+        SparseLocalOnHeapMatrix a = sparseFromArray(new double[][] {{10.0, 11.0}, {0.0, 1.0}}, 2);
+        SparseLocalVector x = sparseFromArray(new double[] {1.0, 2.0});
+        double beta = 2.0;
+        DenseLocalOnHeapVector y = new DenseLocalOnHeapVector(new double[] {3.0, 4.0});
+
+        DenseLocalOnHeapVector exp = (DenseLocalOnHeapVector)y.times(beta).plus(a.times(x).times(alpha));
+
+        Blas.gemv(alpha, a, x, beta, y);
+
+        Assert.assertEquals(exp, y);
+    }
+
+    /** Tests 'gemv' operation for sparse matrix A, sparse vector x and dense vector y. */
+    @Test
+    public void testGemvSparseSparseDense() {
+        // y := alpha * A * x + beta * y
+        double alpha = 3.0;
+        DenseLocalOnHeapMatrix a = new DenseLocalOnHeapMatrix(new double[][] {{10.0, 11.0}, {0.0, 1.0}}, 2);
+        SparseLocalVector x = sparseFromArray(new double[] {1.0, 2.0});
+        double beta = 2.0;
+        DenseLocalOnHeapVector y = new DenseLocalOnHeapVector(new double[] {3.0, 4.0});
+
+        DenseLocalOnHeapVector exp = (DenseLocalOnHeapVector)y.times(beta).plus(a.times(x).times(alpha));
+
+        Blas.gemv(alpha, a, x, beta, y);
+
+        Assert.assertEquals(exp, y);
+    }
+
+    /** Tests 'gemv' operation for dense matrix A, dense vector x and dense vector y. */
+    @Test
+    public void testGemvDenseDenseDense() {
+        // y := alpha * A * x + beta * y
+        double alpha = 3.0;
+        DenseLocalOnHeapMatrix a = new DenseLocalOnHeapMatrix(new double[][] {{10.0, 11.0}, {0.0, 1.0}}, 2);
+        DenseLocalOnHeapVector x = new DenseLocalOnHeapVector(new double[] {1.0, 2.0});
+        double beta = 2.0;
+        DenseLocalOnHeapVector y = new DenseLocalOnHeapVector(new double[] {3.0, 4.0});
+
+        DenseLocalOnHeapVector exp = (DenseLocalOnHeapVector)y.times(beta).plus(a.times(x).times(alpha));
+
+        Blas.gemv(alpha, a, x, beta, y);
+
+        Assert.assertEquals(exp, y);
+    }
+
+    /**
+     * Create a sparse vector from array.
+     *
+     * @param arr Array with vector elements.
+     * @return sparse local on-heap vector.
+     */
+    private static SparseLocalVector sparseFromArray(double[] arr) {
+        SparseLocalVector res = new SparseLocalVector(2, StorageConstants.RANDOM_ACCESS_MODE);
+
+        for (int i = 0; i < arr.length; i++)
+            res.setX(i, arr[i]);
+
+        return res;
+    }
+
+    /**
+     * Create a sparse matrix from array.
+     *
+     * @param arr Array with matrix elements.
+     * @param rows Number of rows in target matrix.
+     * @return sparse local on-heap matrix.
+     */
+    private static SparseLocalOnHeapMatrix sparseFromArray(double[][] arr, int rows) {
+        int cols = arr[0].length;
+        SparseLocalOnHeapMatrix res = new SparseLocalOnHeapMatrix(rows, cols);
+
+        for (int i = 0; i < rows; i++)
+            for (int j = 0; j < cols; j++)
+                res.set(i, j, arr[i][j]);
+
+        return res;
+    }
+
+    /**
+     * Checks if two vectors have equal elements.
+     *
+     * @param a Matrix a.
+     * @param b Vector b
+     * @return true if vectors are equal element-wise, false otherwise.
+     */
+    private static boolean elementsEqual(Vector a, Vector b) {
+        int n = b.size();
+
+        for (int i = 0; i < n; i++)
+            if (a.get(i) != b.get(i))
+                return false;
+
+        return true;
+    }
+
+    /**
+     * Creates dense local on-heap matrix from vector v entities filtered by bipredicate p.
+     *
+     * @param v Vector with entities for matrix to be created.
+     * @param rows Rows number in the target matrix.
+     * @param acsMode column or row major mode.
+     * @param p bipredicate to filter entities by.
+     * @return dense local on-heap matrix.
+     */
+    private static DenseLocalOnHeapMatrix fromVector(DenseLocalOnHeapVector v, int rows, int acsMode,
+        BiPredicate<Integer, Integer> p) {
+        double[] data = v.getStorage().data();
+        int cols = data.length / rows;
+        double[] d = new double[data.length];
+
+        int iLim = acsMode == StorageConstants.ROW_STORAGE_MODE ? rows : cols;
+        int jLim = acsMode == StorageConstants.ROW_STORAGE_MODE ? cols : rows;
+
+        int shift = 0;
+
+        for (int i = 0; i < iLim; i++)
+            for (int j = 0; j < jLim; j++) {
+                int ind = i * jLim + j;
+
+                if (!p.test(i, j)) {
+                    shift++;
+                    d[ind] = 0.0;
+                    continue;
+                }
+                d[ind] = data[ind - shift];
+            }
+
+        return new DenseLocalOnHeapMatrix(d, rows, acsMode);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplMainTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplMainTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplMainTestSuite.java
index 4d245b4..974b7bb 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplMainTestSuite.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplMainTestSuite.java
@@ -27,7 +27,8 @@ import org.junit.runners.Suite;
 @Suite.SuiteClasses({
     MathImplLocalTestSuite.class,
     MathImplDistributedTestSuite.class,
-    TracerTest.class
+    TracerTest.class,
+    BlasTest.class
 })
 public class MathImplMainTestSuite {
     // No-op.

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/MatrixViewConstructorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/MatrixViewConstructorTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/MatrixViewConstructorTest.java
index 82564cb..3e9cdfe 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/MatrixViewConstructorTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/MatrixViewConstructorTest.java
@@ -108,7 +108,7 @@ public class MatrixViewConstructorTest {
             assertEquals(m.isDense(), delegateStorage.isDense());
             assertEquals(m.isArrayBased(), delegateStorage.isArrayBased());
 
-            assertArrayEquals(m.getStorage().data(), delegateStorage.data());
+            assertArrayEquals(m.getStorage().data(), delegateStorage.data(), 0.0);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixArrayStorageTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixArrayStorageTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixArrayStorageTest.java
index 569ed57..3395422 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixArrayStorageTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixArrayStorageTest.java
@@ -54,10 +54,10 @@ public class MatrixArrayStorageTest extends MatrixBaseStorageTest<ArrayMatrixSto
     /** */
     @Test
     public void data() throws Exception {
-        double[][] data = storage.data();
+        double[] data = storage.data();
         assertNotNull(MathTestConstants.NULL_VAL, data);
-        assertTrue(MathTestConstants.UNEXPECTED_VAL, data.length == MathTestConstants.STORAGE_SIZE);
-        assertTrue(MathTestConstants.UNEXPECTED_VAL, data[0].length == MathTestConstants.STORAGE_SIZE);
+        assertTrue(MathTestConstants.UNEXPECTED_VAL, data.length == MathTestConstants.STORAGE_SIZE *
+            MathTestConstants.STORAGE_SIZE);
     }
 
 }