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/23 17:57:26 UTC

[2/2] ignite git commit: ignite-5280 SparseDistributedMatrix refactoring

ignite-5280 SparseDistributedMatrix refactoring

Signed-off-by: Andrey Gura <ag...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/46ec148c
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/46ec148c
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/46ec148c

Branch: refs/heads/master
Commit: 46ec148ca9ae7ecc668c2c0bb9547140d05d68e2
Parents: 4fe8f76
Author: Yury Babak <yb...@gridgain.com>
Authored: Wed Aug 23 20:53:08 2017 +0300
Committer: Andrey Gura <ag...@apache.org>
Committed: Wed Aug 23 20:53:41 2017 +0300

----------------------------------------------------------------------
 .../ml/math/matrix/CacheMatrixExample.java      |   4 +-
 .../ml/math/vector/CacheVectorExample.java      |   4 +-
 modules/ml/pom.xml                              |   1 -
 .../clustering/KMeansDistributedClusterer.java  |  55 +-
 .../ignite/ml/math/IdentityValueMapper.java     |   2 +
 .../apache/ignite/ml/math/MatrixKeyMapper.java  |  30 -
 .../apache/ignite/ml/math/MatrixStorage.java    |   7 +
 .../org/apache/ignite/ml/math/ValueMapper.java  |  37 --
 .../apache/ignite/ml/math/VectorKeyMapper.java  |  29 -
 .../ignite/ml/math/distributed/CacheUtils.java  | 546 ++++++++++++++++++
 .../ml/math/distributed/DistributedStorage.java |  35 ++
 .../ml/math/distributed/MatrixKeyMapper.java    |  33 ++
 .../ignite/ml/math/distributed/ValueMapper.java |  37 ++
 .../ml/math/distributed/VectorKeyMapper.java    |  32 ++
 .../math/distributed/keys/BlockMatrixKey.java   |  30 +
 .../math/distributed/keys/MatrixCacheKey.java   |  35 ++
 .../math/distributed/keys/RowColMatrixKey.java  |  30 +
 .../distributed/keys/impl/BlockMatrixKey.java   | 144 +++++
 .../distributed/keys/impl/SparseMatrixKey.java  | 142 +++++
 .../distributed/keys/impl/package-info.java     |  22 +
 .../ml/math/distributed/keys/package-info.java  |  22 +
 .../ml/math/distributed/package-info.java       |  22 +
 .../apache/ignite/ml/math/impls/CacheUtils.java | 559 -------------------
 .../ml/math/impls/matrix/CacheMatrix.java       |   6 +-
 .../impls/matrix/DenseLocalOnHeapMatrix.java    |   4 +-
 .../matrix/SparseBlockDistributedMatrix.java    |  16 +-
 .../impls/matrix/SparseDistributedMatrix.java   |  83 ++-
 .../storage/matrix/BaseBlockMatrixKey.java      |  41 --
 .../impls/storage/matrix/BlockMatrixKey.java    | 144 -----
 .../storage/matrix/BlockMatrixStorage.java      |  38 +-
 .../storage/matrix/CacheMatrixStorage.java      |   9 +-
 .../matrix/DenseOffHeapMatrixStorage.java       |   5 +
 .../storage/matrix/DiagonalMatrixStorage.java   |   5 +
 .../storage/matrix/FunctionMatrixStorage.java   |   5 +
 .../storage/matrix/MatrixDelegateStorage.java   |   5 +
 .../storage/matrix/PivotedMatrixStorage.java    |   5 +
 .../storage/matrix/RandomMatrixStorage.java     |   5 +
 .../matrix/SparseDistributedMatrixStorage.java  |  54 +-
 .../matrix/SparseLocalOnHeapMatrixStorage.java  |   6 +-
 .../storage/vector/CacheVectorStorage.java      |   4 +-
 .../ml/math/impls/vector/CacheVector.java       |   6 +-
 .../ml/math/impls/matrix/CacheMatrixTest.java   |   2 +-
 .../impls/matrix/MatrixKeyMapperForTests.java   |   2 +-
 .../SparseDistributedBlockMatrixTest.java       |   7 +-
 .../matrix/SparseDistributedMatrixTest.java     |  40 +-
 .../ml/math/impls/vector/CacheVectorTest.java   |   2 +-
 46 files changed, 1368 insertions(+), 984 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/CacheMatrixExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/CacheMatrixExample.java b/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/CacheMatrixExample.java
index d7bb8ae..a7cbaab 100644
--- a/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/CacheMatrixExample.java
+++ b/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/CacheMatrixExample.java
@@ -23,9 +23,9 @@ import org.apache.ignite.Ignition;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.examples.ml.math.vector.CacheVectorExample;
 import org.apache.ignite.ml.math.IdentityValueMapper;
-import org.apache.ignite.ml.math.MatrixKeyMapper;
 import org.apache.ignite.ml.math.Tracer;
-import org.apache.ignite.ml.math.ValueMapper;
+import org.apache.ignite.ml.math.distributed.MatrixKeyMapper;
+import org.apache.ignite.ml.math.distributed.ValueMapper;
 import org.apache.ignite.ml.math.functions.Functions;
 import org.apache.ignite.ml.math.impls.matrix.CacheMatrix;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/examples/src/main/ml/org/apache/ignite/examples/ml/math/vector/CacheVectorExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/ml/org/apache/ignite/examples/ml/math/vector/CacheVectorExample.java b/examples/src/main/ml/org/apache/ignite/examples/ml/math/vector/CacheVectorExample.java
index 14ec43b..4253ac1 100644
--- a/examples/src/main/ml/org/apache/ignite/examples/ml/math/vector/CacheVectorExample.java
+++ b/examples/src/main/ml/org/apache/ignite/examples/ml/math/vector/CacheVectorExample.java
@@ -22,8 +22,8 @@ import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.ml.math.IdentityValueMapper;
-import org.apache.ignite.ml.math.ValueMapper;
-import org.apache.ignite.ml.math.VectorKeyMapper;
+import org.apache.ignite.ml.math.distributed.ValueMapper;
+import org.apache.ignite.ml.math.distributed.VectorKeyMapper;
 import org.apache.ignite.ml.math.impls.vector.CacheVector;
 
 /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/pom.xml
----------------------------------------------------------------------
diff --git a/modules/ml/pom.xml b/modules/ml/pom.xml
index 8774157..7d5d64f 100644
--- a/modules/ml/pom.xml
+++ b/modules/ml/pom.xml
@@ -91,7 +91,6 @@
             <groupId>com.github.fommil.netlib</groupId>
             <artifactId>core</artifactId>
             <version>${netlibjava.version}</version>
-            <type>pom</type>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
index 2ef61ad..d6a3fc3 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
@@ -29,23 +29,26 @@ import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.VectorUtils;
+import org.apache.ignite.ml.math.distributed.CacheUtils;
+import org.apache.ignite.ml.math.distributed.keys.impl.SparseMatrixKey;
 import org.apache.ignite.ml.math.exceptions.ConvergenceException;
 import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
 import org.apache.ignite.ml.math.functions.Functions;
 import org.apache.ignite.ml.math.functions.IgniteBiFunction;
-import org.apache.ignite.ml.math.impls.CacheUtils;
 import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
 import org.apache.ignite.ml.math.impls.storage.matrix.SparseDistributedMatrixStorage;
 import org.apache.ignite.ml.math.util.MapUtil;
 import org.apache.ignite.ml.math.util.MatrixUtil;
 
-import static org.apache.ignite.ml.math.impls.CacheUtils.distributedFold;
+import static org.apache.ignite.ml.math.distributed.CacheUtils.distributedFold;
 import static org.apache.ignite.ml.math.util.MatrixUtil.localCopyOf;
 
 /**
  * Clustering algorithm based on Bahmani et al. paper and Apache Spark class with corresponding functionality.
  *
+ * TODO: IGNITE-6059, add block matrix support.
+ *
  * @see <a href="http://theory.stanford.edu/~sergei/papers/vldb12-kmpar.pdf">Scalable K-Means++(wikipedia)</a>
  */
 public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistributedMatrix> {
@@ -80,6 +83,8 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
         MathIllegalArgumentException, ConvergenceException {
         SparseDistributedMatrix pointsCp = (SparseDistributedMatrix)points.like(points.rowSize(), points.columnSize());
 
+        String cacheName = ((SparseDistributedMatrixStorage)points.getStorage()).cacheName();
+
         // TODO: IGNITE-5825, this copy is very ineffective, just for POC. Immutability of data should be guaranteed by other methods
         // such as logical locks for example.
         pointsCp.assign(points);
@@ -93,7 +98,7 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
 
         // Execute iterations of Lloyd's algorithm until converged
         while (iteration < maxIterations && !converged) {
-            SumsAndCounts stats = getSumsAndCounts(centers, dim, uid);
+            SumsAndCounts stats = getSumsAndCounts(centers, dim, uid, cacheName);
 
             converged = true;
 
@@ -119,6 +124,8 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
         // Initialize empty centers and point costs.
         int ptsCnt = points.rowSize();
 
+        String cacheName = ((SparseDistributedMatrixStorage)points.getStorage()).cacheName();
+
         // Initialize the first center to a random point.
         Vector sample = localCopyOf(points.viewRow(rnd.nextInt(ptsCnt)));
 
@@ -137,7 +144,7 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
 
         while (step < initSteps) {
             // We assume here that costs can fit into memory of one node.
-            ConcurrentHashMap<Integer, Double> newCosts = getNewCosts(points, newCenters);
+            ConcurrentHashMap<Integer, Double> newCosts = getNewCosts(points, newCenters, cacheName);
 
             // Merge costs with new costs.
             for (Integer ind : newCosts.keySet())
@@ -145,7 +152,7 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
 
             double sumCosts = costs.values().stream().mapToDouble(Double::valueOf).sum();
 
-            newCenters = getNewCenters(k, costs, uid, sumCosts);
+            newCenters = getNewCenters(k, costs, uid, sumCosts, cacheName);
             centers.addAll(newCenters);
 
             step++;
@@ -159,7 +166,7 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
             // Finally, we might have a set of more than k distinct candidate centers; weight each
             // candidate by the number of points in the dataset mapping to it and run a local k-means++
             // on the weighted centers to pick k of them
-            ConcurrentHashMap<Integer, Integer> centerInd2Weight = weightCenters(uid, distinctCenters);
+            ConcurrentHashMap<Integer, Integer> centerInd2Weight = weightCenters(uid, distinctCenters, cacheName);
 
             List<Double> weights = new ArrayList<>(centerInd2Weight.size());
 
@@ -174,12 +181,12 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
 
     /** */
     private List<Vector> getNewCenters(int k, ConcurrentHashMap<Integer, Double> costs, IgniteUuid uid,
-        double sumCosts) {
-        return distributedFold(SparseDistributedMatrixStorage.ML_CACHE_NAME,
-            (IgniteBiFunction<Cache.Entry<IgniteBiTuple<Integer, IgniteUuid>, Map<Integer, Double>>,
+        double sumCosts, String cacheName) {
+        return distributedFold(cacheName,
+            (IgniteBiFunction<Cache.Entry<SparseMatrixKey, Map<Integer, Double>>,
                 List<Vector>,
                 List<Vector>>)(vectorWithIndex, list) -> {
-                Integer ind = vectorWithIndex.getKey().get1();
+                Integer ind = vectorWithIndex.getKey().index();
 
                 double prob = costs.get(ind) * 2.0 * k / sumCosts;
 
@@ -188,7 +195,7 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
 
                 return list;
             },
-            key -> key.get2().equals(uid),
+            key -> key.matrixId().equals(uid),
             (list1, list2) -> {
                 list1.addAll(list2);
                 return list1;
@@ -198,17 +205,17 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
     }
 
     /** */
-    private ConcurrentHashMap<Integer, Double> getNewCosts(SparseDistributedMatrix points, List<Vector> newCenters) {
-        return distributedFold(SparseDistributedMatrixStorage.ML_CACHE_NAME,
-            (IgniteBiFunction<Cache.Entry<IgniteBiTuple<Integer, IgniteUuid>, ConcurrentHashMap<Integer, Double>>,
+    private ConcurrentHashMap<Integer, Double> getNewCosts(SparseDistributedMatrix points, List<Vector> newCenters, String cacheName) {
+        return distributedFold(cacheName,
+            (IgniteBiFunction<Cache.Entry<SparseMatrixKey, ConcurrentHashMap<Integer, Double>>,
                 ConcurrentHashMap<Integer, Double>,
                 ConcurrentHashMap<Integer, Double>>)(vectorWithIndex, map) -> {
                 for (Vector center : newCenters)
-                    map.merge(vectorWithIndex.getKey().get1(), distance(vectorWithIndex.getValue(), center), Functions.MIN);
+                    map.merge(vectorWithIndex.getKey().index(), distance(vectorWithIndex.getValue(), center), Functions.MIN);
 
                 return map;
             },
-            key -> key.get2().equals(points.getUUID()),
+            key -> key.matrixId().equals(points.getUUID()),
             (map1, map2) -> {
                 map1.putAll(map2);
                 return map1;
@@ -216,9 +223,9 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
     }
 
     /** */
-    private ConcurrentHashMap<Integer, Integer> weightCenters(IgniteUuid uid, List<Vector> distinctCenters) {
-        return distributedFold(SparseDistributedMatrixStorage.ML_CACHE_NAME,
-            (IgniteBiFunction<Cache.Entry<IgniteBiTuple<Integer, IgniteUuid>, Map<Integer, Double>>,
+    private ConcurrentHashMap<Integer, Integer> weightCenters(IgniteUuid uid, List<Vector> distinctCenters, String cacheName) {
+        return distributedFold(cacheName,
+            (IgniteBiFunction<Cache.Entry<SparseMatrixKey, Map<Integer, Double>>,
                 ConcurrentHashMap<Integer, Integer>,
                 ConcurrentHashMap<Integer, Integer>>)(vectorWithIndex, countMap) -> {
                 Integer resInd = -1;
@@ -239,7 +246,7 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
                 countMap.compute(resInd, (ind, v) -> v != null ? v + 1 : 1);
                 return countMap;
             },
-            key -> key.get2().equals(uid),
+            key -> key.matrixId().equals(uid),
             (map1, map2) -> MapUtil.mergeMaps(map1, map2, (integer, integer2) -> integer2 + integer,
                 ConcurrentHashMap::new),
             new ConcurrentHashMap<>());
@@ -251,9 +258,9 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
     }
 
     /** */
-    private SumsAndCounts getSumsAndCounts(Vector[] centers, int dim, IgniteUuid uid) {
-        return CacheUtils.distributedFold(SparseDistributedMatrixStorage.ML_CACHE_NAME,
-            (IgniteBiFunction<Cache.Entry<IgniteBiTuple<Integer, IgniteUuid>, Map<Integer, Double>>, SumsAndCounts, SumsAndCounts>)(entry, counts) -> {
+    private SumsAndCounts getSumsAndCounts(Vector[] centers, int dim, IgniteUuid uid, String cacheName) {
+        return CacheUtils.distributedFold(cacheName,
+            (IgniteBiFunction<Cache.Entry<SparseMatrixKey, Map<Integer, Double>>, SumsAndCounts, SumsAndCounts>)(entry, counts) -> {
                 Map<Integer, Double> vec = entry.getValue();
 
                 IgniteBiTuple<Integer, Double> closest = findClosest(centers, VectorUtils.fromMap(vec, false));
@@ -270,7 +277,7 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
 
                 return counts;
             },
-            key -> key.get2().equals(uid),
+            key -> key.matrixId().equals(uid),
             SumsAndCounts::merge, new SumsAndCounts()
         );
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/IdentityValueMapper.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/IdentityValueMapper.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/IdentityValueMapper.java
index 3c94edd..615006e 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/IdentityValueMapper.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/IdentityValueMapper.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.ml.math;
 
+import org.apache.ignite.ml.math.distributed.ValueMapper;
+
 /**
  * Identity value mapper.
  */

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixKeyMapper.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixKeyMapper.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixKeyMapper.java
deleted file mode 100644
index 54d2088..0000000
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixKeyMapper.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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;
-
-/**
- * Maps {@link Matrix} row and column index to cache key.
- */
-public interface MatrixKeyMapper<K> extends KeyMapper<K> {
-    /**
-     * @param x Matrix row index.
-     * @param y Matrix column index.
-     * @return Cache key for given row and column.
-     */
-    public K apply(int x, int y);
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
index a80e066..e4f9e40 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
@@ -55,6 +55,13 @@ public interface MatrixStorage extends Externalizable, StorageOpsMetrics, Destro
     public int storageMode();
 
     /**
+     * @return Matrix access mode.
+     *
+     * @see StorageConstants
+     */
+    public int accessMode();
+
+    /**
      * Gets underlying data, if {@link StorageOpsMetrics#isArrayBased()} returns {@code false} this method return
      * copy of data. The data must be adapted for {@link Blas}.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/ValueMapper.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/ValueMapper.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/ValueMapper.java
deleted file mode 100644
index f0776a3..0000000
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/ValueMapper.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.io.Serializable;
-
-/**
- * Utility mapper that can be used to map arbitrary values types to and from double.
- */
-public interface ValueMapper<V> extends Serializable {
-    /**
-     * @param v Value to map from double.
-     * @return Mapped value.
-     */
-    public V fromDouble(double v);
-
-    /**
-     * @param v Value to map to double.
-     * @return Mapped value.
-     */
-    public double toDouble(V v);
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/VectorKeyMapper.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/VectorKeyMapper.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/VectorKeyMapper.java
deleted file mode 100644
index 4b8fadb..0000000
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/VectorKeyMapper.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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;
-
-/**
- * Maps {@link Vector} element index to cache key.
- */
-public interface VectorKeyMapper<K> extends KeyMapper<K> {
-    /**
-     * @param i Vector element index.
-     * @return Cache key for given element index.
-     */
-    public K apply(int i);
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
new file mode 100644
index 0000000..9a73c5a
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
@@ -0,0 +1,546 @@
+/*
+ * 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.distributed;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.function.BinaryOperator;
+import javax.cache.Cache;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.query.ScanQuery;
+import org.apache.ignite.cluster.ClusterGroup;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.processors.cache.CacheEntryImpl;
+import org.apache.ignite.internal.util.typedef.internal.A;
+import org.apache.ignite.lang.IgniteCallable;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.lang.IgniteRunnable;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.ml.math.KeyMapper;
+import org.apache.ignite.ml.math.distributed.keys.RowColMatrixKey;
+import org.apache.ignite.ml.math.distributed.keys.impl.BlockMatrixKey;
+import org.apache.ignite.ml.math.functions.IgniteBiFunction;
+import org.apache.ignite.ml.math.functions.IgniteConsumer;
+import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.functions.IgniteFunction;
+import org.apache.ignite.ml.math.impls.matrix.BlockEntry;
+
+/**
+ * Distribution-related misc. support.
+ *
+ * TODO: IGNITE-5102, fix sparse key filters.
+ */
+public class CacheUtils {
+    /**
+     * Cache entry support.
+     *
+     * @param <K>
+     * @param <V>
+     */
+    public static class CacheEntry<K, V> {
+        /** */
+        private Cache.Entry<K, V> entry;
+        /** */
+        private IgniteCache<K, V> cache;
+
+        /**
+         * @param entry Original cache entry.
+         * @param cache Cache instance.
+         */
+        CacheEntry(Cache.Entry<K, V> entry, IgniteCache<K, V> cache) {
+            this.entry = entry;
+            this.cache = cache;
+        }
+
+        /**
+         *
+         *
+         */
+        public Cache.Entry<K, V> entry() {
+            return entry;
+        }
+
+        /**
+         *
+         *
+         */
+        public IgniteCache<K, V> cache() {
+            return cache;
+        }
+    }
+
+    /**
+     * Gets local Ignite instance.
+     */
+    public static Ignite ignite() {
+        return Ignition.localIgnite();
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @param k Key into the cache.
+     * @param <K> Key type.
+     * @return Cluster group for given key.
+     */
+    public static <K> ClusterGroup groupForKey(String cacheName, K k) {
+        return ignite().cluster().forNode(ignite().affinity(cacheName).mapKeyToNode(k));
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @param keyMapper {@link KeyMapper} to validate cache key.
+     * @param valMapper {@link ValueMapper} to obtain double value for given cache key.
+     * @param <K> Cache key object type.
+     * @param <V> Cache value object type.
+     * @return Sum of the values obtained for valid keys.
+     */
+    public static <K, V> double sum(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper) {
+        Collection<Double> subSums = fold(cacheName, (CacheEntry<K, V> ce, Double acc) -> {
+            if (keyMapper.isValid(ce.entry().getKey())) {
+                double v = valMapper.toDouble(ce.entry().getValue());
+
+                return acc == null ? v : acc + v;
+            }
+            else
+                return acc;
+        });
+
+        return sum(subSums);
+    }
+
+    /**
+     * @param matrixUuid Matrix UUID.
+     * @return Sum obtained using sparse logic.
+     */
+    @SuppressWarnings("unchecked")
+    public static <K, V> double sparseSum(IgniteUuid matrixUuid, String cacheName) {
+        A.notNull(matrixUuid, "matrixUuid");
+        A.notNull(cacheName, "cacheName");
+
+        Collection<Double> subSums = fold(cacheName, (CacheEntry<K, V> ce, Double acc) -> {
+            V v = ce.entry().getValue();
+
+            double sum = 0.0;
+
+            if (v instanceof Map) {
+                Map<Integer, Double> map = (Map<Integer, Double>)v;
+
+                sum = sum(map.values());
+            }
+            else if (v instanceof BlockEntry) {
+                BlockEntry be = (BlockEntry)v;
+
+                sum = be.sum();
+            }
+            else
+                throw new UnsupportedOperationException();
+
+            return acc == null ? sum : acc + sum;
+        }, sparseKeyFilter(matrixUuid));
+
+        return sum(subSums);
+    }
+
+    /**
+     * @param c {@link Collection} of double values to sum.
+     * @return Sum of the values.
+     */
+    private static double sum(Collection<Double> c) {
+        double sum = 0.0;
+
+        for (double d : c)
+            sum += d;
+
+        return sum;
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @param keyMapper {@link KeyMapper} to validate cache key.
+     * @param valMapper {@link ValueMapper} to obtain double value for given cache key.
+     * @param <K> Cache key object type.
+     * @param <V> Cache value object type.
+     * @return Minimum value for valid keys.
+     */
+    public static <K, V> double min(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper) {
+        Collection<Double> mins = fold(cacheName, (CacheEntry<K, V> ce, Double acc) -> {
+            if (keyMapper.isValid(ce.entry().getKey())) {
+                double v = valMapper.toDouble(ce.entry().getValue());
+
+                if (acc == null)
+                    return v;
+                else
+                    return Math.min(acc, v);
+            }
+            else
+                return acc;
+        });
+
+        return Collections.min(mins);
+    }
+
+    /**
+     * @param matrixUuid Matrix UUID.
+     * @return Minimum value obtained using sparse logic.
+     */
+    @SuppressWarnings("unchecked")
+    public static <K, V> double sparseMin(IgniteUuid matrixUuid, String cacheName) {
+        A.notNull(matrixUuid, "matrixUuid");
+        A.notNull(cacheName, "cacheName");
+
+        Collection<Double> mins = fold(cacheName, (CacheEntry<K, V> ce, Double acc) -> {
+            V v = ce.entry().getValue();
+
+            double min;
+
+            if (v instanceof Map) {
+                Map<Integer, Double> map = (Map<Integer, Double>)v;
+
+                min = Collections.min(map.values());
+            }
+            else if (v instanceof BlockEntry) {
+                BlockEntry be = (BlockEntry)v;
+
+                min = be.minValue();
+            }
+            else
+                throw new UnsupportedOperationException();
+
+            if (acc == null)
+                return min;
+            else
+                return Math.min(acc, min);
+
+        }, sparseKeyFilter(matrixUuid));
+
+        return Collections.min(mins);
+    }
+
+    /**
+     * @param matrixUuid Matrix UUID.
+     * @return Maximum value obtained using sparse logic.
+     */
+    @SuppressWarnings("unchecked")
+    public static <K, V> double sparseMax(IgniteUuid matrixUuid, String cacheName) {
+        A.notNull(matrixUuid, "matrixUuid");
+        A.notNull(cacheName, "cacheName");
+
+        Collection<Double> maxes = fold(cacheName, (CacheEntry<K, V> ce, Double acc) -> {
+            V v = ce.entry().getValue();
+
+            double max;
+
+            if (v instanceof Map) {
+                Map<Integer, Double> map = (Map<Integer, Double>)v;
+
+                max = Collections.max(map.values());
+            }
+            else if (v instanceof BlockEntry) {
+                BlockEntry be = (BlockEntry)v;
+
+                max = be.maxValue();
+            }
+            else
+                throw new UnsupportedOperationException();
+
+            if (acc == null)
+                return max;
+            else
+                return Math.max(acc, max);
+
+        }, sparseKeyFilter(matrixUuid));
+
+        return Collections.max(maxes);
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @param keyMapper {@link KeyMapper} to validate cache key.
+     * @param valMapper {@link ValueMapper} to obtain double value for given cache key.
+     * @param <K> Cache key object type.
+     * @param <V> Cache value object type.
+     * @return Maximum value for valid keys.
+     */
+    public static <K, V> double max(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper) {
+        Collection<Double> maxes = fold(cacheName, (CacheEntry<K, V> ce, Double acc) -> {
+            if (keyMapper.isValid(ce.entry().getKey())) {
+                double v = valMapper.toDouble(ce.entry().getValue());
+
+                if (acc == null)
+                    return v;
+                else
+                    return Math.max(acc, v);
+            }
+            else
+                return acc;
+        });
+
+        return Collections.max(maxes);
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @param keyMapper {@link KeyMapper} to validate cache key.
+     * @param valMapper {@link ValueMapper} to obtain double value for given cache key.
+     * @param mapper Mapping {@link IgniteFunction}.
+     * @param <K> Cache key object type.
+     * @param <V> Cache value object type.
+     */
+    public static <K, V> void map(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper,
+        IgniteFunction<Double, Double> mapper) {
+        foreach(cacheName, (CacheEntry<K, V> ce) -> {
+            K k = ce.entry().getKey();
+
+            if (keyMapper.isValid(k))
+                // Actual assignment.
+                ce.cache().put(k, valMapper.fromDouble(mapper.apply(valMapper.toDouble(ce.entry().getValue()))));
+        });
+    }
+
+    /**
+     * @param matrixUuid Matrix UUID.
+     * @param mapper Mapping {@link IgniteFunction}.
+     */
+    @SuppressWarnings("unchecked")
+    public static <K, V> void sparseMap(IgniteUuid matrixUuid, IgniteDoubleFunction<Double> mapper, String cacheName) {
+        A.notNull(matrixUuid, "matrixUuid");
+        A.notNull(cacheName, "cacheName");
+        A.notNull(mapper, "mapper");
+
+        foreach(cacheName, (CacheEntry<K, V> ce) -> {
+            K k = ce.entry().getKey();
+
+            V v = ce.entry().getValue();
+
+            if (v instanceof Map) {
+                Map<Integer, Double> map = (Map<Integer, Double>)v;
+
+                for (Map.Entry<Integer, Double> e : (map.entrySet()))
+                    e.setValue(mapper.apply(e.getValue()));
+
+            }
+            else if (v instanceof BlockEntry) {
+                BlockEntry be = (BlockEntry)v;
+
+                be.map(mapper);
+            }
+            else
+                throw new UnsupportedOperationException();
+
+            ce.cache().put(k, v);
+        }, sparseKeyFilter(matrixUuid));
+    }
+
+    /**
+     * Filter for distributed matrix keys.
+     *
+     * @param matrixUuid Matrix uuid.
+     */
+    private static <K> IgnitePredicate<K> sparseKeyFilter(IgniteUuid matrixUuid) {
+        return key -> {
+            if (key instanceof BlockMatrixKey)
+                return ((BlockMatrixKey)key).matrixId().equals(matrixUuid);
+            else if (key instanceof RowColMatrixKey)
+                return ((RowColMatrixKey)key).matrixId().equals(matrixUuid);
+            else
+                throw new UnsupportedOperationException();
+        };
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @param fun An operation that accepts a cache entry and processes it.
+     * @param <K> Cache key object type.
+     * @param <V> Cache value object type.
+     */
+    public static <K, V> void foreach(String cacheName, IgniteConsumer<CacheEntry<K, V>> fun) {
+        foreach(cacheName, fun, null);
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @param fun An operation that accepts a cache entry and processes it.
+     * @param keyFilter Cache keys filter.
+     * @param <K> Cache key object type.
+     * @param <V> Cache value object type.
+     */
+    public static <K, V> void foreach(String cacheName, IgniteConsumer<CacheEntry<K, V>> fun,
+        IgnitePredicate<K> keyFilter) {
+        bcast(cacheName, () -> {
+            Ignite ignite = Ignition.localIgnite();
+            IgniteCache<K, V> cache = ignite.getOrCreateCache(cacheName);
+
+            int partsCnt = ignite.affinity(cacheName).partitions();
+
+            // Use affinity in filter for scan query. Otherwise we accept consumer in each node which is wrong.
+            Affinity affinity = ignite.affinity(cacheName);
+            ClusterNode locNode = ignite.cluster().localNode();
+
+            // Iterate over all partitions. Some of them will be stored on that local node.
+            for (int part = 0; part < partsCnt; part++) {
+                int p = part;
+
+                // Iterate over given partition.
+                // Query returns an empty cursor if this partition is not stored on this node.
+                for (Cache.Entry<K, V> entry : cache.query(new ScanQuery<K, V>(part, (k, v) -> affinity.mapPartitionToNode(p) == locNode && (keyFilter == null || keyFilter.apply(k)))))
+                    fun.accept(new CacheEntry<>(entry, cache));
+            }
+        });
+    }
+
+    /**
+     * <b>Currently fold supports only commutative operations.<b/>
+     *
+     * @param cacheName Cache name.
+     * @param folder Fold function operating over cache entries.
+     * @param <K> Cache key object type.
+     * @param <V> Cache value object type.
+     * @param <A> Fold result type.
+     * @return Fold operation result.
+     */
+    public static <K, V, A> Collection<A> fold(String cacheName, IgniteBiFunction<CacheEntry<K, V>, A, A> folder) {
+        return fold(cacheName, folder, null);
+    }
+
+    /**
+     * <b>Currently fold supports only commutative operations.<b/>
+     *
+     * @param cacheName Cache name.
+     * @param folder Fold function operating over cache entries.
+     * @param <K> Cache key object type.
+     * @param <V> Cache value object type.
+     * @param <A> Fold result type.
+     * @return Fold operation result.
+     */
+    public static <K, V, A> Collection<A> fold(String cacheName, IgniteBiFunction<CacheEntry<K, V>, A, A> folder,
+        IgnitePredicate<K> keyFilter) {
+        return bcast(cacheName, () -> {
+            Ignite ignite = Ignition.localIgnite();
+            IgniteCache<K, V> cache = ignite.getOrCreateCache(cacheName);
+
+            int partsCnt = ignite.affinity(cacheName).partitions();
+
+            // Use affinity in filter for ScanQuery. Otherwise we accept consumer in each node which is wrong.
+            Affinity affinity = ignite.affinity(cacheName);
+            ClusterNode locNode = ignite.cluster().localNode();
+
+            A a = null;
+
+            // Iterate over all partitions. Some of them will be stored on that local node.
+            for (int part = 0; part < partsCnt; part++) {
+                int p = part;
+
+                // Iterate over given partition.
+                // Query returns an empty cursor if this partition is not stored on this node.
+                for (Cache.Entry<K, V> entry : cache.query(new ScanQuery<K, V>(part,
+                    (k, v) -> affinity.mapPartitionToNode(p) == locNode && (keyFilter == null || keyFilter.apply(k)))))
+                    a = folder.apply(new CacheEntry<>(entry, cache), a);
+            }
+
+            return a;
+        });
+    }
+
+    /**
+     * Distributed version of fold operation.
+     *
+     * @param cacheName Cache name.
+     * @param folder Folder.
+     * @param keyFilter Key filter.
+     * @param accumulator Accumulator.
+     * @param zeroVal Zero value.
+     */
+    public static <K, V, A> A distributedFold(String cacheName, IgniteBiFunction<Cache.Entry<K, V>, A, A> folder,
+        IgnitePredicate<K> keyFilter, BinaryOperator<A> accumulator, A zeroVal) {
+        return sparseFold(cacheName, folder, keyFilter, accumulator, zeroVal, null, null, 0,
+            false);
+    }
+
+    /**
+     * Sparse version of fold. This method also applicable to sparse zeroes.
+     *
+     * @param cacheName Cache name.
+     * @param folder Folder.
+     * @param keyFilter Key filter.
+     * @param accumulator Accumulator.
+     * @param zeroVal Zero value.
+     * @param defVal Def value.
+     * @param defKey Def key.
+     * @param defValCnt Def value count.
+     * @param isNilpotent Is nilpotent.
+     */
+    private static <K, V, A> A sparseFold(String cacheName, IgniteBiFunction<Cache.Entry<K, V>, A, A> folder,
+        IgnitePredicate<K> keyFilter, BinaryOperator<A> accumulator, A zeroVal, V defVal, K defKey, long defValCnt,
+        boolean isNilpotent) {
+
+        A defRes = zeroVal;
+
+        if (!isNilpotent)
+            for (int i = 0; i < defValCnt; i++)
+                defRes = folder.apply(new CacheEntryImpl<>(defKey, defVal), defRes);
+
+        Collection<A> totalRes = bcast(cacheName, () -> {
+            Ignite ignite = Ignition.localIgnite();
+            IgniteCache<K, V> cache = ignite.getOrCreateCache(cacheName);
+
+            int partsCnt = ignite.affinity(cacheName).partitions();
+
+            // Use affinity in filter for ScanQuery. Otherwise we accept consumer in each node which is wrong.
+            Affinity affinity = ignite.affinity(cacheName);
+            ClusterNode locNode = ignite.cluster().localNode();
+
+            A a = zeroVal;
+
+            // Iterate over all partitions. Some of them will be stored on that local node.
+            for (int part = 0; part < partsCnt; part++) {
+                int p = part;
+
+                // Iterate over given partition.
+                // Query returns an empty cursor if this partition is not stored on this node.
+                for (Cache.Entry<K, V> entry : cache.query(new ScanQuery<K, V>(part,
+                    (k, v) -> affinity.mapPartitionToNode(p) == locNode && (keyFilter == null || keyFilter.apply(k)))))
+                    a = folder.apply(entry, a);
+            }
+
+            return a;
+        });
+        totalRes.add(defRes);
+        return totalRes.stream().reduce(zeroVal, accumulator);
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @param run {@link Runnable} to broadcast to cache nodes for given cache name.
+     */
+    public static void bcast(String cacheName, IgniteRunnable run) {
+        ignite().compute(ignite().cluster().forCacheNodes(cacheName)).broadcast(run);
+    }
+
+    /**
+     * @param cacheName Cache name.
+     * @param call {@link IgniteCallable} to broadcast to cache nodes for given cache name.
+     * @param <A> Type returned by the callable.
+     */
+    public static <A> Collection<A> bcast(String cacheName, IgniteCallable<A> call) {
+        return ignite().compute(ignite().cluster().forCacheNodes(cacheName)).broadcast(call);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/DistributedStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/DistributedStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/DistributedStorage.java
new file mode 100644
index 0000000..7b58d1d
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/DistributedStorage.java
@@ -0,0 +1,35 @@
+/*
+ * 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.distributed;
+
+import java.util.Set;
+
+/**
+ * Extension for any distributed storage.
+ */
+public interface DistributedStorage<K> {
+    /**
+     * Build a keyset for this storage.
+     */
+    public Set<K> getAllKeys();
+
+    /**
+     * @return The name of cache used in this storage.
+     */
+    public String cacheName();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/MatrixKeyMapper.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/MatrixKeyMapper.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/MatrixKeyMapper.java
new file mode 100644
index 0000000..2a93328
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/MatrixKeyMapper.java
@@ -0,0 +1,33 @@
+/*
+ * 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.distributed;
+
+import org.apache.ignite.ml.math.KeyMapper;
+import org.apache.ignite.ml.math.Matrix;
+
+/**
+ * Maps {@link Matrix} row and column index to cache key.
+ */
+public interface MatrixKeyMapper<K> extends KeyMapper<K> {
+    /**
+     * @param x Matrix row index.
+     * @param y Matrix column index.
+     * @return Cache key for given row and column.
+     */
+    public K apply(int x, int y);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/ValueMapper.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/ValueMapper.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/ValueMapper.java
new file mode 100644
index 0000000..c94cfb6
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/ValueMapper.java
@@ -0,0 +1,37 @@
+/*
+ * 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.distributed;
+
+import java.io.Serializable;
+
+/**
+ * Utility mapper that can be used to map arbitrary values types to and from double.
+ */
+public interface ValueMapper<V> extends Serializable {
+    /**
+     * @param v Value to map from double.
+     * @return Mapped value.
+     */
+    public V fromDouble(double v);
+
+    /**
+     * @param v Value to map to double.
+     * @return Mapped value.
+     */
+    public double toDouble(V v);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/VectorKeyMapper.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/VectorKeyMapper.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/VectorKeyMapper.java
new file mode 100644
index 0000000..de08d7b
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/VectorKeyMapper.java
@@ -0,0 +1,32 @@
+/*
+ * 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.distributed;
+
+import org.apache.ignite.ml.math.KeyMapper;
+import org.apache.ignite.ml.math.Vector;
+
+/**
+ * Maps {@link Vector} element index to cache key.
+ */
+public interface VectorKeyMapper<K> extends KeyMapper<K> {
+    /**
+     * @param i Vector element index.
+     * @return Cache key for given element index.
+     */
+    public K apply(int i);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/BlockMatrixKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/BlockMatrixKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/BlockMatrixKey.java
new file mode 100644
index 0000000..c55b950
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/BlockMatrixKey.java
@@ -0,0 +1,30 @@
+/*
+ * 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.distributed.keys;
+
+import org.apache.ignite.ml.math.impls.matrix.SparseBlockDistributedMatrix;
+
+/**
+ * Cache key for blocks in {@link SparseBlockDistributedMatrix}.
+ */
+public interface BlockMatrixKey extends MatrixCacheKey {
+    /**
+     * @return block id.
+     */
+    public long blockId();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixCacheKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixCacheKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixCacheKey.java
new file mode 100644
index 0000000..669e9a4
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixCacheKey.java
@@ -0,0 +1,35 @@
+/*
+ * 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.distributed.keys;
+
+import org.apache.ignite.lang.IgniteUuid;
+
+/**
+ * Base matrix cache key.
+ */
+public interface MatrixCacheKey {
+    /**
+     * @return matrix id.
+     */
+    public IgniteUuid matrixId();
+
+    /**
+     * @return affinity key.
+     */
+    public IgniteUuid affinityKey();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/RowColMatrixKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/RowColMatrixKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/RowColMatrixKey.java
new file mode 100644
index 0000000..168f49f
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/RowColMatrixKey.java
@@ -0,0 +1,30 @@
+/*
+ * 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.distributed.keys;
+
+import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
+
+/**
+ * Cache key for {@link SparseDistributedMatrix}.
+ */
+public interface RowColMatrixKey extends MatrixCacheKey {
+    /**
+     *  Return index value(blockId, Row/Col index, etc.)
+     */
+    public int index();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/BlockMatrixKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/BlockMatrixKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/BlockMatrixKey.java
new file mode 100644
index 0000000..5fd1a16
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/BlockMatrixKey.java
@@ -0,0 +1,144 @@
+/*
+ * 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.distributed.keys.impl;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.binary.BinaryReader;
+import org.apache.ignite.binary.BinaryWriter;
+import org.apache.ignite.binary.Binarylizable;
+import org.apache.ignite.internal.binary.BinaryUtils;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.ml.math.impls.matrix.BlockEntry;
+import org.apache.ignite.ml.math.impls.matrix.SparseBlockDistributedMatrix;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Key implementation for {@link BlockEntry} using for {@link SparseBlockDistributedMatrix}.
+ */
+public class BlockMatrixKey implements org.apache.ignite.ml.math.distributed.keys.BlockMatrixKey, Externalizable, Binarylizable {
+    /** */
+    private static final long serialVersionUID = 0L;
+    /** Block ID */
+    private long blockId;
+    /** Matrix ID */
+    private IgniteUuid matrixUuid;
+    /** Block affinity key. */
+    private IgniteUuid affinityKey;
+
+    /**
+     * Empty constructor required for {@link Externalizable}.
+     */
+    public BlockMatrixKey() {
+        // No-op.
+    }
+
+    /**
+     * Construct matrix block key.
+     *
+     * @param blockId Block id.
+     * @param matrixUuid Matrix uuid.
+     * @param affinityKey Affinity key.
+     */
+    public BlockMatrixKey(long blockId, IgniteUuid matrixUuid, @Nullable IgniteUuid affinityKey) {
+        assert blockId >= 0;
+        assert matrixUuid != null;
+
+        this.blockId = blockId;
+        this.matrixUuid = matrixUuid;
+        this.affinityKey = affinityKey;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long blockId() {
+        return blockId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteUuid matrixId() {
+        return matrixUuid;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteUuid affinityKey() {
+        return affinityKey;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        U.writeGridUuid(out, matrixUuid);
+        U.writeGridUuid(out, affinityKey);
+        out.writeLong(blockId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        matrixUuid = U.readGridUuid(in);
+        affinityKey = U.readGridUuid(in);
+        blockId = in.readLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
+        BinaryRawWriter out = writer.rawWriter();
+
+        BinaryUtils.writeIgniteUuid(out, matrixUuid);
+        BinaryUtils.writeIgniteUuid(out, affinityKey);
+        out.writeLong(blockId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
+        BinaryRawReader in = reader.rawReader();
+
+        matrixUuid = BinaryUtils.readIgniteUuid(in);
+        affinityKey = BinaryUtils.readIgniteUuid(in);
+        blockId = in.readLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        return matrixUuid.hashCode() + (int)(blockId ^ (blockId >>> 32));
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (obj == this)
+            return true;
+
+        if (obj == null || obj.getClass() != getClass())
+            return false;
+
+        BlockMatrixKey that = (BlockMatrixKey)obj;
+
+        return blockId == that.blockId && matrixUuid.equals(that.matrixUuid) && F.eq(affinityKey, that.affinityKey);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(BlockMatrixKey.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
new file mode 100644
index 0000000..0c34c8b
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
@@ -0,0 +1,142 @@
+/*
+ * 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.distributed.keys.impl;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.binary.BinaryReader;
+import org.apache.ignite.binary.BinaryWriter;
+import org.apache.ignite.binary.Binarylizable;
+import org.apache.ignite.internal.binary.BinaryUtils;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.ml.math.distributed.keys.RowColMatrixKey;
+import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
+
+/**
+ * Key implementation for {@link SparseDistributedMatrix}.
+ */
+public class SparseMatrixKey implements RowColMatrixKey, Externalizable, Binarylizable {
+    /** */
+    private int idx;
+    /** */
+    private IgniteUuid matrixId;
+    /** */
+    private IgniteUuid affinityKey;
+
+    /**
+     * Default constructor (required by Externalizable).
+     */
+    public SparseMatrixKey(){
+
+    }
+
+    /**
+     * Build Key.
+     */
+    public SparseMatrixKey(int idx, IgniteUuid matrixId, IgniteUuid affinityKey) {
+        assert idx >= 0 : "Index must be positive.";
+        assert matrixId != null : "Matrix id can`t be null.";
+
+        this.idx = idx;
+        this.matrixId = matrixId;
+        this.affinityKey = affinityKey;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int index() {
+        return idx;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteUuid matrixId() {
+        return matrixId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteUuid affinityKey() {
+        return affinityKey;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        U.writeGridUuid(out, matrixId);
+        U.writeGridUuid(out, affinityKey);
+        out.writeInt(idx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        matrixId = U.readGridUuid(in);
+        affinityKey = U.readGridUuid(in);
+        idx = in.readInt();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
+        BinaryRawWriter out = writer.rawWriter();
+
+        BinaryUtils.writeIgniteUuid(out, matrixId);
+        BinaryUtils.writeIgniteUuid(out, affinityKey);
+        out.writeInt(idx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
+        BinaryRawReader in = reader.rawReader();
+
+        matrixId = BinaryUtils.readIgniteUuid(in);
+        affinityKey = BinaryUtils.readIgniteUuid(in);
+        idx = in.readInt();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res += res * 37 + matrixId.hashCode();
+        res += res * 37 + idx;
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (obj == this)
+            return true;
+
+        if (obj == null || obj.getClass() != getClass())
+            return false;
+
+        SparseMatrixKey that = (SparseMatrixKey)obj;
+
+        return idx == that.idx && matrixId.equals(that.matrixId) && F.eq(affinityKey, that.affinityKey);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(SparseMatrixKey.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/package-info.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/package-info.java
new file mode 100644
index 0000000..3a68ee2
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains matrix cache key implementations.
+ */
+package org.apache.ignite.ml.math.distributed.keys.impl;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/package-info.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/package-info.java
new file mode 100644
index 0000000..8954c6e
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains matrix cache keys.
+ */
+package org.apache.ignite.ml.math.distributed.keys;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/46ec148c/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/package-info.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/package-info.java
new file mode 100644
index 0000000..ad7399b
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains classes for distribution support.
+ */
+package org.apache.ignite.ml.math.distributed;
\ No newline at end of file