Improve mapreduce sharding for inequality filters

Summary:
This improves the sharding algorithm when inequality filters are used with DatastoreInputReader. Right now inequality filters are handled by splitting the property range uniformly. This results in really uneven sharding in many cases.

Note that we are limited to one property on which we can use an inequality filter. If we use the `__scatter__` property, we implicitly use this up on the keys! More info:
https://code.google.com/p/appengine-mapreduce/wiki/ScatterPropertyImplementation
https://developers.google.com/appengine/docs/python/datastore/queries#Python_Restrictions_on_queries

For more detail, see the emails here: https://groups.google.com/a/khanacademy.org/forum/#!topic/analytics-blackhole/6_MLbJbL10o

Now, we split the property range into 16 (we can change this) times more sub-ranges and redistribute the work across shards. For instance, if we have 256 shards, this artificially creates 256 * 16 = 4096 ranges and spreads them out. The shards will get the following range numbers:

- Shard 0: gets 0, 256, 512, ..., 3840
- Shard 1: gets 1, 257, 513, ..., 3841
- ...
- Shard 255: gets 255, 511, 1023, ..., 4095

I chose this approach because it's not data dependent. Other approaches would typically require splitting the ranges non-uniformly, which would in turn require sampling the data. The implementation chains together iterators and implements the appropriate JSON serialization. I found this pretty elegant, but I'm open to other ideas!

After lots of debugging, this works locally, i.e. learning gain pipelines produce the same results as before. I'm going to run it on a znd to check that the sharding actually improves.

Test Plan: Run locally (for correctness) and on znd (for sharding)

Reviewers: mattfaus, tom

CC: jascha, eliana, jace, benjaminhaley

Differential Revision: http://phabricator.khanacademy.org/D6147