Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions distarray/local/localarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ def _init(self, dim_data, grid_shape, dtype=None, buf=None, comm=None):
# object's data.
self.global_index = GlobalIndex(self.maps, self.local_array.view())

self.base = None
self.ctypes = None
self.base = None # mimic numpy.ndarray.base

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think this is not needed? This is here from Brian's original code.

http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.base.html

self.ctypes = None # mimic numpy.ndarray.ctypes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly for this, though it seems like this should be an attribute that raises NotImplementedError or something.

http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.ctypes.html

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither are implemented. And I think to raise here these would have to be @propertys. I don't think we should bother right now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks to me like base is set to precisely the right thing.

On Wed, Apr 9, 2014 at 2:52 PM, Blake Griffith notifications@github.comwrote:

In distarray/local/localarray.py:

@@ -222,9 +222,6 @@ def _init(self, dim_data, grid_shape, dtype=None, buf=None, comm=None):
# object's data.
self.global_index = GlobalIndex(self.maps, self.local_array.view())

  •    self.base = None
    
  •    self.ctypes = None
    

Neither are implemented. And I think to raise here these would have to be
@propertys. I don't think we should bother right now.

Reply to this email directly or view it on GitHubhttps://github.com//pull/274/files#r11455498
.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are correct. Since we don't have slicing base is None should always be the case. But none of the other behavior is implemented.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I vote for keeping both of these in here, as there is some meaning to them.


def _init_grid_shape(self, grid_shape):

Expand Down
2 changes: 2 additions & 0 deletions distarray/local/tests/paralleltest_localarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ def test_grid_shape(self):
self.larr = LocalArray((100, 10, 300), dist=('b', 'n', 'c'), comm=self.comm)
self.assertEqual(self.larr.grid_shape, (2, 1, 6))
self.larr = LocalArray((100, 50, 300), dist='b', comm=self.comm)
self.assertEqual(self.larr.grid_shape, (2, 1, 6))
self.larr = LocalArray((100, 100, 150), dist='b', comm=self.comm)
self.assertEqual(self.larr.grid_shape, (2, 2, 3))

def test_ones_in_grid_shape(self):
Expand Down
22 changes: 9 additions & 13 deletions distarray/metadata_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,6 @@ class GridShapeError(Exception):
pass


def make_grid_shape(global_shape, dist, comm_size):
""" Generate a `grid_shape` from `global_shape` tuple and `dist` tuple.

Does not assume that `dim_data` has `proc_grid_size` set for each
dimension.
"""
distdims = tuple(i for (i, v) in enumerate(dist) if v != 'n')
return optimize_grid_shape(global_shape, distdims, comm_size)


def normalize_grid_shape(grid_shape, ndims):
""" Adds 1's to grid_shape so it has `ndims` dimensions.
"""
Expand All @@ -58,8 +48,13 @@ def validate_grid_shape(grid_shape, dist, comm_size):
return grid_shape


def optimize_grid_shape(shape, distdims, comm_size):
''' Attempts to allocate processes optimally for distributed dimensions.
def make_grid_shape(shape, dist, comm_size):
""" Generate a `grid_shape` from `shape` tuple and `dist` tuple.

Does not assume that `dim_data` has `proc_grid_size` set for each
dimension.

Attempts to allocate processes optimally for distributed dimensions.

Parameters
----------
Expand All @@ -78,7 +73,8 @@ def optimize_grid_shape(shape, distdims, comm_size):
------
GridShapeError if not possible to distribute `comm_size` processes over
number of dimensions.
'''
"""
distdims = tuple(i for (i, v) in enumerate(dist) if v != 'n')
ndistdim = len(distdims)

if ndistdim == 1:
Expand Down
25 changes: 25 additions & 0 deletions distarray/tests/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,30 @@ def test_purge_and_dump_keys(self):
self.assertEqual(num_keys2, num_keys0)


class TestPrimeCluster(unittest.TestCase):

@classmethod
def setUpClass(cls):
cls.context = Context(targets=range(3))

def test_1D(self):
a = self.context.empty((3,))
self.assertEqual(a.grid_shape, (3,))

def test_2D(self):
a = self.context.empty((3, 3))
b = self.context.empty((3, 3), dist=('n', 'b'))
self.assertEqual(a.grid_shape, (3, 1))
self.assertEqual(b.grid_shape, (1, 3))

def test_3D(self):
a = self.context.empty((3, 3, 3))
b = self.context.empty((3, 3, 3), dist=('n', 'b', 'n'))
c = self.context.empty((3, 3, 3), dist=('n', 'n', 'b'))
self.assertEqual(a.grid_shape, (3, 1, 1))
self.assertEqual(b.grid_shape, (1, 3, 1))
self.assertEqual(c.grid_shape, (1, 1, 3))


if __name__ == '__main__':
unittest.main(verbosity=2)
20 changes: 12 additions & 8 deletions distarray/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ class TestMultPartitions(unittest.TestCase):
Test the multiplicative parition code.
"""

def test_both_methods(self):
"""
Do the two methods of computing the multiplicative partitions agree?
"""
for s in [2, 3]:
for n in range(2, 512):
self.assertEqual(utils.mult_partitions(n, s),
utils.create_factors(n, s))
def test_mult_partitions(self):
self.assertEqual(utils.mult_partitions(1, 2), [(1, 1)])
self.assertEqual(utils.mult_partitions(2, 2), [(1, 2)])
self.assertEqual(utils.mult_partitions(1, 7), [(1,) * 7])
self.assertEqual(utils.mult_partitions(7, 2), [(1, 7)])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a little concerned that we would no longer have the alternate method available to test against. The previous test_both_methods seemed like a pretty thorough test that mult_partitions worked as expected. I guess that create_factors wouldn't handle the situation of allowing 1 as a factor?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Also, create_factors was unused in the code.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think create_factors was really a test for mult_partitions, I think probably a simple-but-slow method that mult_partitions could be tested against. So it would have probably more properly lived in the test code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create_factors isn't so simple, it calls out to two other functions. Which themselves should be tested. It is complicated enough to warrant its own tests. And I'm not sure writing meta-tests for functions only used in tests is worthwhile.

I also deleted one of the functions create_factors called, divisors. And another that just wasn't used anywhere.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Tue, Apr 8, 2014 at 10:05 AM, Blake Griffith notifications@github.comwrote:

In distarray/tests/test_utils.py:

@@ -16,14 +16,18 @@ class TestMultPartitions(unittest.TestCase):
Test the multiplicative parition code.
"""

  • def test_both_methods(self):
  •    """
    
  •    Do the two methods of computing the multiplicative partitions agree?
    
  •    """
    
  •    for s in [2, 3]:
    

create_factors isn't so simple, it calls out to two other functions.
Which themselves should be tested. It is complicated enough to warrant its
own tests. And I'm not sure writing meta-tests for functions only used in
tests is worthwhile.

Given unlimited resources, we'd do the full testing with multiple versions,
etc. @markkness feel free to make a wishlist issue with your testing
ideas, but otherwise, I'm +1 on just testing the factorisation function in
use and removing the others.

I also deleted one of the functions create_factors called, divisors. And
another that just wasn't used anywhere.

Reply to this email directly or view it on GitHubhttps://github.com//pull/274/files#r11393841
.

Kurt W. Smith, Ph.D. ksmith@enthought.com
Enthought, Inc. http://www.enthought.com | 512.536.1057

self.assertEqual(utils.mult_partitions(7, 3), [(1, 1, 7)])
self.assertEqual(utils.mult_partitions(16, 4), [(1, 1, 1, 16),
(1, 1, 2, 8),
(1, 1, 4, 4),
(1, 2, 2, 4),
(2, 2, 2, 2)])
self.assertEqual(utils.mult_partitions(6, 3), [(1, 1, 6), (1, 2, 3)])


class TestSanitizeIndices(unittest.TestCase):
Expand Down
39 changes: 2 additions & 37 deletions distarray/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@
from distarray.externals.six import next


def divisors(n):
i = 2
while i<n:
if n % i == 0:
yield i
i += 1


def multi_for(iterables):
if not iterables:
Expand All @@ -28,22 +21,6 @@ def multi_for(iterables):
yield (item,) + rest_tuple


def create_factors(n, size=2):
divs = list(divisors(n))
factors = []
for indices in multi_for( [range(p) for p in size*[len(divs)]] ):
total = 1
for i in indices:
total = total*divs[i]
if n == total:
factor = [divs[i] for i in indices]
factor.sort()
factor = tuple(factor)
if factor not in factors:
factors.append(factor)
return factors


def divisors_minmax(n, dmin, dmax):
"""Find the divisors of n in the interval (dmin,dmax]."""
i = dmin+1
Expand Down Expand Up @@ -75,10 +52,10 @@ def mult_partitions(n, s):
>>> mult_partitions(52,2)
[(2, 26), (4, 13)]
"""
return [tuple(flatten(p)) for p in mult_partitions_recurs(n,s)]
return [tuple(flatten(p)) for p in mult_partitions_recurs(n, s)]


def mult_partitions_recurs(n, s, pd=1):
def mult_partitions_recurs(n, s, pd=0):
if s == 1:
return [n]
divs = divisors_minmax(n, pd, int(sqrt(n)))
Expand Down Expand Up @@ -107,18 +84,6 @@ def mirror_sort(seq, ref_seq):
return newseq


def outer_zip(seqa, seqb):
"""An outer product, but using zip rather than multiplication.

>>> a = 2*range(4)
>>> b = range(8)
>>> outer_zip(a,b)
[[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7)], [(1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7)], [(2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7)], [(3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7)], [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7)], [(1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7)], [(2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7)], [(3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7)]]

"""
return [[(i,j) for j in seqb] for i in seqa]


def _raise_nie():
msg = "This has not yet been implemented for distributed arrays"
raise NotImplementedError(msg)
Expand Down