From 8c35cf49c61d9af362ff7c0e1d59654ac61a1cac Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sun, 28 May 2017 09:47:21 -0700 Subject: [PATCH 01/10] Remove redundant codegen branch in SOURCE_AND_TARGET_INDEX_FINDER --- boxtree/tree_build_kernels.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/boxtree/tree_build_kernels.py b/boxtree/tree_build_kernels.py index d59a9f6..b246899 100644 --- a/boxtree/tree_build_kernels.py +++ b/boxtree/tree_build_kernels.py @@ -1031,9 +1031,6 @@ SOURCE_AND_TARGET_INDEX_FINDER = ElementwiseTemplate( target_nr + 1 - (particle_id_t) is_source - box_start_target_nr; } - %elif srcntgts_have_extent: - box_source_counts_nonchild[box_id] = 0; - box_target_counts_nonchild[box_id] = 0; %endif // {{{ last particle for this or the parents' boxes? update counts -- GitLab From 30a98d4e7912f6163bb0620f0e317309c5073cab Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sun, 28 May 2017 09:50:37 -0700 Subject: [PATCH 02/10] Fix tree-build recallocation of box_morton_bin_counts when particles have extents --- boxtree/tree_build.py | 60 ++++++++++++++++++++++++++++++++++++++----- test/test_tree.py | 33 ++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/boxtree/tree_build.py b/boxtree/tree_build.py index 7a014cd..191f4b7 100644 --- a/boxtree/tree_build.py +++ b/boxtree/tree_build.py @@ -744,10 +744,12 @@ class TreeBuilder(object): split_box_ids = my_realloc_nocopy(split_box_ids) - # FIXME: This can be reused across iterations, saving the cost - # of the particle scan. Right now there isn't a reallocator - # written for it. - box_morton_bin_counts, evt = my_realloc_zeros_nocopy( + # *Most*, but not *all* of the values in this array are + # rewritten when the morton scan is redone. Specifically, + # only the box morton bin counts of boxes on the level + # currently being processed are written-but we need to + # retain the box morton bin counts from the higher levels. + box_morton_bin_counts, evt = my_realloc_zeros_and_renumber( box_morton_bin_counts) resize_events.append(evt) @@ -1030,6 +1032,46 @@ class TreeBuilder(object): level += 1 have_oversize_split_box.fill(0) + # {{{ check that nonchild part of box_morton_bin_counts is consistent + + if debug and 0: + h_box_morton_bin_counts = box_morton_bin_counts.get() + h_box_srcntgt_counts_cumul = box_srcntgt_counts_cumul.get() + h_box_child_ids = tuple(bci.get() for bci in box_child_ids) + + has_mismatch = False + for ibox in range(level_start_box_nrs[-1]): + is_leaf = all(bci[ibox] == 0 for bci in h_box_child_ids) + if is_leaf: + # nonchild count only found in box_info kernel + continue + + if h_box_srcntgt_counts_cumul[ibox] == 0: + # empty boxes don't have box_morton_bin_counts written + continue + + kid_sum = sum( + h_box_srcntgt_counts_cumul[bci[ibox]] + for bci in h_box_child_ids + if bci[ibox] != 0) + + if ( + h_box_srcntgt_counts_cumul[ibox] + != + h_box_morton_bin_counts[ibox]["nonchild_srcntgts"] + + kid_sum): + print("MISMATCH", level, ibox) + has_mismatch = True + + assert not has_mismatch + print("LEVEL %d OK" % level) + + del h_box_morton_bin_counts + del h_box_srcntgt_counts_cumul + del h_box_child_ids + + # }}} + end_time = time() elapsed = end_time-start_time npasses = level+1 @@ -1065,8 +1107,14 @@ class TreeBuilder(object): del highest_possibly_split_box_nr if debug: - assert (box_srcntgt_counts_nonchild.get() - <= box_srcntgt_counts_cumul.get()[:nboxes]).all() + h_box_srcntgt_counts_nonchild = box_srcntgt_counts_nonchild.get() + h_box_srcntgt_counts_cumul = box_srcntgt_counts_cumul.get() + + assert (h_box_srcntgt_counts_nonchild + <= h_box_srcntgt_counts_cumul[:nboxes]).all() + + del h_box_srcntgt_counts_nonchild + del h_box_srcntgt_counts_cumul # }}} diff --git a/test/test_tree.py b/test/test_tree.py index 0857787..07cda4d 100644 --- a/test/test_tree.py +++ b/test/test_tree.py @@ -462,6 +462,9 @@ def test_extent_tree(ctx_getter, dims, do_plot=False): targets = make_normal_particle_array(queue, ntargets, dims, dtype, seed=19) + refine_weights = cl.array.zeros(queue, nsources+ntargets, np.int32) + refine_weights[:nsources] = 1 + from pyopencl.clrandom import PhiloxGenerator rng = PhiloxGenerator(queue.context, seed=13) source_radii = 2**rng.uniform(queue, nsources, dtype=dtype, @@ -474,8 +477,19 @@ def test_extent_tree(ctx_getter, dims, do_plot=False): queue.finish() dev_tree, _ = tb(queue, sources, targets=targets, - source_radii=source_radii, target_radii=target_radii, - max_particles_in_box=10, debug=True) + source_radii=source_radii, + target_radii=target_radii, + + refine_weights=refine_weights, + max_leaf_refine_weight=20, + + #max_particles_in_box=10, + + # Set artificially small, to exercise the reallocation code. + nboxes_guess=10, + + debug=True, + stick_out_factor=0) logger.info("transfer tree, check orderings") @@ -490,6 +504,7 @@ def test_extent_tree(ctx_getter, dims, do_plot=False): unsorted_targets = np.array([pi.get() for pi in targets]) unsorted_source_radii = source_radii.get() unsorted_target_radii = target_radii.get() + assert (sorted_sources == unsorted_sources[:, tree.user_source_ids]).all() assert (sorted_source_radii @@ -511,6 +526,20 @@ def test_extent_tree(ctx_getter, dims, do_plot=False): # {{{ check sources, targets + assert np.sum(tree.box_source_counts_nonchild) == nsources + assert np.sum(tree.box_target_counts_nonchild) == ntargets + + for ibox in range(tree.nboxes): + kid_sum = sum( + tree.box_target_counts_cumul[ichild_box] + for ichild_box in tree.box_child_ids[:, ibox] + if ichild_box != 0) + assert ( + tree.box_target_counts_cumul[ibox] + == + tree.box_target_counts_nonchild[ibox] + + kid_sum), ibox + for ibox in range(tree.nboxes): extent_low, extent_high = tree.get_box_extent(ibox) -- GitLab From f8e6648ece3f1d2436189ca40b682dd9582d85c9 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sun, 28 May 2017 09:50:56 -0700 Subject: [PATCH 03/10] Add plotting code to test_extent_tree --- test/test_tree.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/test_tree.py b/test/test_tree.py index 07cda4d..bd8908b 100644 --- a/test/test_tree.py +++ b/test/test_tree.py @@ -495,6 +495,20 @@ def test_extent_tree(ctx_getter, dims, do_plot=False): tree = dev_tree.get(queue=queue) + if do_plot: + import matplotlib.pyplot as pt + pt.plot(sources[0].get(), sources[1].get(), "rx") + pt.plot(targets[0].get(), targets[1].get(), "g+") + + from boxtree.visualization import TreePlotter + plotter = TreePlotter(tree) + plotter.draw_tree(fill=False, edgecolor="black", zorder=10) + plotter.draw_box_numbers() + plotter.set_bounding_box() + + pt.gca().set_aspect("equal", "datalim") + pt.show() + sorted_sources = np.array(list(tree.sources)) sorted_targets = np.array(list(tree.targets)) sorted_source_radii = tree.source_radii -- GitLab From 659eff3448bc124b3edf9e77cc3a7b6ea8762e34 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sun, 28 May 2017 12:23:13 -0700 Subject: [PATCH 04/10] Tree build reallocation: Don't try to renumber box_morton_bin_counts --- boxtree/tree_build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boxtree/tree_build.py b/boxtree/tree_build.py index 191f4b7..4850b77 100644 --- a/boxtree/tree_build.py +++ b/boxtree/tree_build.py @@ -749,7 +749,7 @@ class TreeBuilder(object): # only the box morton bin counts of boxes on the level # currently being processed are written-but we need to # retain the box morton bin counts from the higher levels. - box_morton_bin_counts, evt = my_realloc_zeros_and_renumber( + box_morton_bin_counts, evt = my_realloc_zeros( box_morton_bin_counts) resize_events.append(evt) -- GitLab From 27d49172854e33115f742ef4347c78692dee5b73 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sun, 28 May 2017 12:23:30 -0700 Subject: [PATCH 05/10] Force reallocations in test_level_restriction --- test/test_tree.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/test_tree.py b/test/test_tree.py index bd8908b..371e500 100644 --- a/test/test_tree.py +++ b/test/test_tree.py @@ -905,7 +905,10 @@ def test_level_restriction(ctx_getter, dims, skip_prune, lookbehind, do_plot=Fal queue.finish() tree_dev, _ = tb(queue, particles, kind="adaptive-level-restricted", max_particles_in_box=30, debug=True, - skip_prune=skip_prune, lr_lookbehind=lookbehind) + skip_prune=skip_prune, lr_lookbehind=lookbehind, + + # Artificially low to exercise reallocation code + nboxes_guess=10) def find_neighbors(leaf_box_centers, leaf_box_radii): # We use an area query with a ball that is slightly larger than -- GitLab From 7084f01959d8527847487566c7ace80a49bb8e8b Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sun, 28 May 2017 12:23:51 -0700 Subject: [PATCH 06/10] Remove some uses of CompiledKernel to avoid warnings --- boxtree/tools.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/boxtree/tools.py b/boxtree/tools.py index 73039bd..ad078ff 100644 --- a/boxtree/tools.py +++ b/boxtree/tools.py @@ -27,7 +27,7 @@ import numpy as np from pytools import Record, memoize_method import pyopencl as cl import pyopencl.array # noqa -from pyopencl.tools import first_arg_dependent_memoize_nested, dtype_to_c_struct +from pyopencl.tools import dtype_to_c_struct from mako.template import Template from pytools.obj_array import make_obj_array @@ -106,8 +106,7 @@ def make_surface_particle_array(queue, nparticles, dims, dtype, seed=15): import loopy as lp if dims == 2: - @first_arg_dependent_memoize_nested - def get_2d_knl(context, dtype): + def get_2d_knl(dtype): knl = lp.make_kernel( "{[i]: 0<=i Date: Sun, 28 May 2017 12:39:39 -0700 Subject: [PATCH 07/10] Fix: Remove some uses of CompiledKernel to avoid warnings --- boxtree/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boxtree/tools.py b/boxtree/tools.py index ad078ff..ee472de 100644 --- a/boxtree/tools.py +++ b/boxtree/tools.py @@ -197,7 +197,7 @@ def make_uniform_particle_array(queue, nparticles, dims, dtype, seed=15): elif dims == 3: n = int(nparticles**(1/3)) - def get_3d_knl(context, dtype): + def get_3d_knl(dtype): knl = lp.make_kernel( "{[i,j,k]: 0<=i,j,k Date: Sun, 28 May 2017 12:50:53 -0700 Subject: [PATCH 08/10] Fix: Work around Py2 scoping limitations when cleaning up after a diagnostic --- boxtree/tree_build.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/boxtree/tree_build.py b/boxtree/tree_build.py index 4850b77..f91e94c 100644 --- a/boxtree/tree_build.py +++ b/boxtree/tree_build.py @@ -1066,7 +1066,9 @@ class TreeBuilder(object): assert not has_mismatch print("LEVEL %d OK" % level) - del h_box_morton_bin_counts + # Cannot delete in Py 2.7: referred to from nested scope. + h_box_morton_bin_counts = None + del h_box_srcntgt_counts_cumul del h_box_child_ids -- GitLab From ac22a9bd4ed20139c34e7313ee968e2807dbeb9f Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sun, 28 May 2017 13:06:36 -0700 Subject: [PATCH 09/10] Fix: Work around Py2 scoping limitations when cleaning up after a diagnostic --- boxtree/tree_build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boxtree/tree_build.py b/boxtree/tree_build.py index f91e94c..0d57775 100644 --- a/boxtree/tree_build.py +++ b/boxtree/tree_build.py @@ -1067,9 +1067,9 @@ class TreeBuilder(object): print("LEVEL %d OK" % level) # Cannot delete in Py 2.7: referred to from nested scope. - h_box_morton_bin_counts = None + h_box_srcntgt_counts_cumul = None - del h_box_srcntgt_counts_cumul + del h_box_morton_bin_counts del h_box_child_ids # }}} -- GitLab From a49124e18e6f9f999e147cb431a6703e1fe50638 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sun, 28 May 2017 13:17:46 -0700 Subject: [PATCH 10/10] Fix: Work around Py2 scoping limitations when cleaning up after a diagnostic --- boxtree/tree_build.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/boxtree/tree_build.py b/boxtree/tree_build.py index 0d57775..de2140a 100644 --- a/boxtree/tree_build.py +++ b/boxtree/tree_build.py @@ -1116,7 +1116,9 @@ class TreeBuilder(object): <= h_box_srcntgt_counts_cumul[:nboxes]).all() del h_box_srcntgt_counts_nonchild - del h_box_srcntgt_counts_cumul + + # Cannot delete in Py 2.7: referred to from nested scope. + h_box_srcntgt_counts_cumul = None # }}} -- GitLab