3

I am trying to perform some numerical computation on a large distributed data set. The algorithms fit the MapReduce model well with the additional property that output from the map step is small in size compared to the input data. Data can be considered read-only and is statically distributed over the nodes (except for re-balancing on fail-over). Note that this is somewhat contrary to the standard word-count examples where the input data is sent to the nodes performing the map step.

This implies that the map step shall be executed in parallel on all nodes, processing each node's local data, while it is acceptable that the output from the map step is sent to one node for the reduce step.

What is the best way to implement this with GridGain?

It seems there has been a reduce(..) method on GridCache/GridCacheProjection interfaces in earlier versions of GridGain, but this is not present any longer. Is there any replacement? I am thinking of a mechanism that takes a map closure and executes it distributed on each datum exactly once while avoiding to copy any input data across the network.

The (somewhat manual) approach I have come up with so far is the following:

public class GridBroadcastCountDemo {

    public static void main(String[] args) throws GridException {
        try (Grid grid = GridGain.start(CONFIG_FILE)) {

            GridFuture<Collection<Integer>> future = grid.forRemotes().compute().broadcast(new GridCallable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    GridCache<Integer, float[]> cache = grid.cache(CACHE_NAME);
                    int count = 0;
                    for (float[] array : cache.primaryValues()) {
                        count += array.length;
                    }
                    return count;
                }
            });

            int totalCount = 0;
            for (int count : future.get()) {
                totalCount += count;
            }
            // expect size of input data
            System.out.println(totalCount);
        }
    }
}

There is however no guarantee that each datum is processed exactly once with this approach. E.g. when re-balancing takes place while the GridCallables are executed, part of the data could be processed zero or multiple times.

1 Answers1

1

GridGain Open Source (which is now Apache Ignite) has ComputeTask API which has both, map() and reduce() methods. If you are looking for a reduce() method, then ComputeTask is definitely the right API for you.

For now your implementation is OK. Apache Ignite is adding a feature where a node will not be considered primary until the migration is fully finished. It should be coming soon.

Dmitriy
  • 2,282
  • 1
  • 11
  • 7
  • It's good to know that there will be a feature that ensures keys are not considered primary on multiple nodes during rebalancing. However, erroneously processing some keys multiple times is not so much of a problem (apart from some overhead), because duplicates are easily detected and discarded during the reduce step. The opposite case would be really problematic, if any keys were not processed due to rebalancing going on. Is it possible that this happens, or does GridGain provide any guarantee that there is at least one copy of every primary key at any time? – Qwert Zuiopü Feb 20 '15 at 13:01
  • @QwertZuiopü The opposite case is not possible. GridGain will guarantee that there is at least one copy of a key. – Dmitriy Feb 20 '15 at 16:35
  • @QwertZuiopü By the way, you can track the feature of delayed primary key assignments until the preloading is complete here: https://issues.apache.org/jira/browse/IGNITE-324 – Dmitriy Feb 20 '15 at 19:57
  • Actually, `GridComputeTask.map` and `GridComputeTask.reduce` do not exactly provide the high-level map-reduce abstraction that I was looking for (as described by the original Google paper] ). Of course that can easily be implemented on top of the `ComputeTask` API. Still, it would be nice if GridGain provided it out-of-the-box; optimally ensuring that each primary key is processed exactly once. – Qwert Zuiopü Feb 26 '15 at 20:58
  • @QwertZuiopü Pure MapReduce was never built for performance and is a big overkill for in-memory computing. I am yet to see a performance sensitive use-case that really requires it for real-time processing. See here for more details: http://apacheignite.readme.io/v1.0/docs/compute-tasks – Dmitriy Feb 27 '15 at 05:18
  • @QwertZuiopü Would be nice to find out about your use-case and see why the pure MapReduce (instead of fork-join) is a required for you. – Dmitriy Feb 27 '15 at 05:20
  • I agree that classic MapReduce incurs unnecessary overhead in many cases (and in our particular use case as well). So effectively my request boils down to having a guarantee that each primary key is processed exactly once (and locally, on the node where it is stored) by a ComputeTask. It seems this would indeed be solved by the "delayed primary key assignment" feature you pointed to. – Qwert Zuiopü Feb 27 '15 at 08:17