[yt-svn] commit/yt: 7 new changesets
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Tue Dec 6 08:22:51 PST 2016
7 new commits in yt:
https://bitbucket.org/yt_analysis/yt/commits/5b21d07b4814/
Changeset: 5b21d07b4814
Branch: yt
User: MatthewTurk
Date: 2016-11-28 16:33:11+00:00
Summary: Adding an allocation container / object pool
Affected #: 4 files
diff -r 0bfebdb21e22a03f91a11dff8d455ee17e885e92 -r 5b21d07b4814ecd14e233252dd103c19a8072877 setup.py
--- a/setup.py
+++ b/setup.py
@@ -180,7 +180,7 @@
"particle_mesh_operations", "depth_first_octree", "fortran_reader",
"interpolators", "misc_utilities", "basic_octree", "image_utilities",
"points_in_volume", "quad_tree", "ray_integrators", "mesh_utilities",
- "amr_kdtools", "lenses", "distance_queue"
+ "amr_kdtools", "lenses", "distance_queue", "allocation_container"
]
for ext_name in lib_exts:
cython_extensions.append(
diff -r 0bfebdb21e22a03f91a11dff8d455ee17e885e92 -r 5b21d07b4814ecd14e233252dd103c19a8072877 yt/utilities/lib/allocation_container.pxd
--- /dev/null
+++ b/yt/utilities/lib/allocation_container.pxd
@@ -0,0 +1,35 @@
+"""
+An allocation container and memory pool
+
+
+
+"""
+
+#-----------------------------------------------------------------------------
+# Copyright (c) 2016, yt Development Team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file COPYING.txt, distributed with this software.
+#-----------------------------------------------------------------------------
+
+cimport numpy as np
+from libc.stdlib cimport malloc, free, realloc
+
+cdef struct AllocationContainer:
+ np.uint64_t n
+ np.uint64_t n_assigned
+ np.uint64_t offset
+ np.int64_t con_id # container id
+ void *my_objs
+
+cdef class ObjectPool:
+ cdef public np.uint64_t itemsize
+ cdef np.uint64_t n_con
+ cdef AllocationContainer* containers
+ cdef void allocate_objs(self, int n_objs, np.int64_t con_id = ?) except *
+ cdef void setup_objs(self, void *obj, np.uint64_t count,
+ np.uint64_t offset, np.int64_t con_id)
+ cdef void teardown_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
+ np.int64_t con_id)
+
diff -r 0bfebdb21e22a03f91a11dff8d455ee17e885e92 -r 5b21d07b4814ecd14e233252dd103c19a8072877 yt/utilities/lib/allocation_container.pyx
--- /dev/null
+++ b/yt/utilities/lib/allocation_container.pyx
@@ -0,0 +1,103 @@
+"""
+An allocation container and memory pool
+
+
+
+"""
+
+#-----------------------------------------------------------------------------
+# Copyright (c) 2016, yt Development Team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file COPYING.txt, distributed with this software.
+#-----------------------------------------------------------------------------
+
+cimport numpy as np
+import numpy as np
+
+cdef class ObjectPool:
+ def __cinit__(self):
+ self.containers = NULL
+ self.n_con = 0
+ self.itemsize = -1 # Never use the base class
+
+ def __dealloc__(self):
+ cdef int i
+ cdef AllocationContainer *obj
+ for i in range(self.n_con):
+ obj = &self.containers[i]
+ self.teardown_objs(obj.my_objs, obj.n, obj.offset, obj.con_id)
+ if self.containers != NULL:
+ free(self.containers)
+
+ def __getitem__(self, int i):
+ return self._con_to_array(i)
+
+ def __len__(self):
+ return self.n_con
+
+ def append(self, int n_objs, np.int64_t con_id = -1):
+ self.allocate_objs(n_objs, con_id)
+ return self[self.n_con - 1]
+
+ cdef void allocate_objs(self, int n_objs, np.int64_t con_id = -1) except *:
+ cdef AllocationContainer *n_cont, *prev
+ cdef int n, i, j, k
+ cdef char *obj # char so we can do pointer math
+ self.containers = <AllocationContainer*> realloc(
+ self.containers,
+ sizeof(AllocationContainer) * (self.n_con + 1))
+ n_cont = &self.containers[self.n_con]
+ if self.n_con == 0:
+ n_cont.offset = 0
+ else:
+ prev = &self.containers[self.n_con - 1]
+ n_cont.offset = prev.offset + prev.n
+ self.n_con += 1
+ n_cont.my_objs = malloc(self.itemsize * n_objs)
+ if n_cont.my_objs == NULL:
+ raise MemoryError
+ n_cont.n = n_objs
+ n_cont.n_assigned = 0
+ n_cont.con_id = con_id
+ obj = <char*> n_cont.my_objs
+ self.setup_objs(n_cont.my_objs, n_objs, n_cont.offset, n_cont.con_id)
+
+ cdef void setup_objs(self, void *obj, np.uint64_t count, np.uint64_t
+ offset, np.int64_t con_id):
+ pass
+
+ cdef void teardown_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
+ np.int64_t con_id):
+ # We assume that these are all allocated and have no sub-allocations
+ if obj != NULL:
+ free(obj)
+
+ def to_arrays(self):
+ rv = []
+ cdef int i
+ for i in range(self.n_con):
+ rv.append(self._con_to_array(i))
+ return rv
+
+ def _con_to_array(self, int i):
+ raise NotImplementedError
+
+cdef class BitmaskPool(ObjectPool):
+ def __cinit__(self):
+ # Base class will ALSO be called
+ self.itemsize = sizeof(np.uint8_t)
+
+ cdef void setup_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
+ np.int64_t con_id):
+ cdef np.uint64_t i
+ cdef np.uint8_t *mask = <np.uint8_t *> obj
+ for i in range(n):
+ mask[i] = 0
+
+ def _con_to_array(self, int i):
+ cdef AllocationContainer *obj = &self.containers[i]
+ cdef np.uint8_t[:] o = <np.uint8_t[:obj.n]> (<np.uint8_t*> obj.my_objs)
+ rv = np.asarray(o)
+ return rv
diff -r 0bfebdb21e22a03f91a11dff8d455ee17e885e92 -r 5b21d07b4814ecd14e233252dd103c19a8072877 yt/utilities/lib/tests/test_allocation_container.py
--- /dev/null
+++ b/yt/utilities/lib/tests/test_allocation_container.py
@@ -0,0 +1,22 @@
+from yt.testing import \
+ assert_array_equal, assert_equal
+from yt.utilities.lib.allocation_container import \
+ BitmaskPool
+
+def test_bitmask_pool():
+ bmp = BitmaskPool()
+ assert_equal(len(bmp), 0)
+ bmp.append(100)
+ assert_equal(len(bmp), 1)
+ assert_equal(bmp[0].size, 100)
+ bmp.append(200)
+ assert_equal(len(bmp), 2)
+ assert_equal(bmp[0].size, 100)
+ assert_equal(bmp[1].size, 200)
+ assert_equal(sum(_.size for _ in bmp.to_arrays()), 300)
+ arrs = bmp.to_arrays()
+ assert_equal(arrs[0].size, 100)
+ assert_equal(arrs[1].size, 200)
+ arrs[0][:] = 1
+ arrs = bmp.to_arrays()
+ assert_array_equal(arrs[0], 1)
https://bitbucket.org/yt_analysis/yt/commits/b9e3cef0f25a/
Changeset: b9e3cef0f25a
Branch: yt
User: MatthewTurk
Date: 2016-11-28 18:19:30+00:00
Summary: Initial implementation of OctObjectPool
Affected #: 2 files
diff -r 5b21d07b4814ecd14e233252dd103c19a8072877 -r b9e3cef0f25a25b6bbb94aaa24d7d36a796b56e0 yt/geometry/oct_container.pxd
--- a/yt/geometry/oct_container.pxd
+++ b/yt/geometry/oct_container.pxd
@@ -22,6 +22,8 @@
from .oct_visitors cimport OctVisitor, Oct, cind
from libc.stdlib cimport bsearch, qsort, realloc, malloc, free
from libc.math cimport floor
+from yt.utilities.lib.allocation_container cimport \
+ ObjectPool, AllocationContainer
cdef int ORDER_MAX
diff -r 5b21d07b4814ecd14e233252dd103c19a8072877 -r b9e3cef0f25a25b6bbb94aaa24d7d36a796b56e0 yt/geometry/oct_container.pyx
--- a/yt/geometry/oct_container.pyx
+++ b/yt/geometry/oct_container.pyx
@@ -1049,3 +1049,33 @@
next = this.next
free(this)
this = next
+
+cdef class OctObjectPool(ObjectPool):
+ def __cinit__(self):
+ # Base class will ALSO be called
+ self.itemsize = sizeof(Oct)
+
+ cdef void setup_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
+ np.int64_t con_id):
+ cdef np.uint64_t i
+ cdef Oct* octs = <Oct *> obj
+ for n in range(n):
+ octs[n].file_ind = oct.domain = - 1
+ octs[n].domain_ind = n + offset
+ octs[n].children = NULL
+
+ cdef void teardown_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
+ np.int64_t con_id):
+ cdef np.uint64_t i, j
+ cdef Oct *my_octs = <Oct *> obj
+ for i in range(n):
+ if my_octs[i].children != NULL:
+ free(my_octs[i].children)
+ free(obj)
+
+ def _con_to_array(self, int i):
+ cdef AllocationContainer *obj = &self.containers[i]
+ cdef OctPadded[:] mm = <OctPadded[:obj.n_assigned]> (
+ <OctPadded*> obj.my_objs)
+ rv = np.asarray(mm)
+ return rv
https://bitbucket.org/yt_analysis/yt/commits/38d949eddcf0/
Changeset: 38d949eddcf0
Branch: yt
User: MatthewTurk
Date: 2016-11-28 19:38:00+00:00
Summary: Switching OctContainer to use OctObjectPool.
Affected #: 4 files
diff -r b9e3cef0f25a25b6bbb94aaa24d7d36a796b56e0 -r 38d949eddcf0942047812c03a2974dc72a832667 yt/frontends/artio/_artio_caller.pyx
--- a/yt/frontends/artio/_artio_caller.pyx
+++ b/yt/frontends/artio/_artio_caller.pyx
@@ -7,7 +7,7 @@
SelectorObject, AlwaysSelector, OctreeSubsetSelector
from yt.utilities.lib.fp_utils cimport imax
from yt.geometry.oct_container cimport \
- SparseOctreeContainer
+ SparseOctreeContainer, OctObjectPool
from yt.geometry.oct_visitors cimport Oct
from yt.geometry.particle_deposit cimport \
ParticleDepositOperation
@@ -15,6 +15,8 @@
from libc.string cimport memcpy
import data_structures
from yt.utilities.lib.misc_utilities import OnceIndirect
+from yt.utilities.lib.allocation_container cimport \
+ AllocationContainer
cdef extern from "platform_dep.h":
ctypedef int int32_t
@@ -923,7 +925,7 @@
super(ARTIOOctreeContainer, self).__init__(dims, DLE, DRE)
self.artio_handle = range_handler.artio_handle
self.level_offset = 1
- self.domains = NULL
+ self.domains = OctObjectPool()
self.root_nodes = NULL
@cython.boundscheck(False)
@@ -949,7 +951,7 @@
# We only allow one root oct.
self.append_domain(oct_count)
- self.domains[self.num_domains - 1].con_id = sfc
+ self.domains.containers[self.num_domains - 1].con_id = sfc
oct_ind = -1
ipos = 0
@@ -1009,7 +1011,7 @@
source_arrays = []
ipos = -1
for i in range(self.num_domains):
- ipos = imax(ipos, self.domains[i].n)
+ ipos = imax(ipos, self.domains.containers[i].n)
for i in range(nf):
field_ind[i] = field_indices[i]
# Note that we subtract one, because we're not using the root mesh.
@@ -1029,13 +1031,13 @@
# double-loop to calculate domain_counts
# The cons should be in order
cdef np.int64_t sfc_start, sfc_end
- sfc_start = self.domains[0].con_id
- sfc_end = self.domains[self.num_domains - 1].con_id
+ sfc_start = self.domains.containers[0].con_id
+ sfc_end = self.domains.containers[self.num_domains - 1].con_id
status = artio_grid_cache_sfc_range(handle, sfc_start, sfc_end)
check_artio_status(status)
cdef np.int64_t offset = 0
for si in range(self.num_domains):
- sfc = self.domains[si].con_id
+ sfc = self.domains.containers[si].con_id
status = artio_grid_read_root_cell_begin( handle, sfc,
dpos, NULL, &num_oct_levels, num_octs_per_level)
check_artio_status(status)
diff -r b9e3cef0f25a25b6bbb94aaa24d7d36a796b56e0 -r 38d949eddcf0942047812c03a2974dc72a832667 yt/geometry/oct_container.pxd
--- a/yt/geometry/oct_container.pxd
+++ b/yt/geometry/oct_container.pxd
@@ -52,13 +52,16 @@
OctList *next
Oct *o
+cdef class OctObjectPool(ObjectPool):
+ pass
+
cdef OctList *OctList_append(OctList *list, Oct *o)
cdef int OctList_count(OctList *list)
cdef void OctList_delete(OctList *list)
cdef class OctreeContainer:
cdef OctAllocationContainer *cont
- cdef OctAllocationContainer **domains
+ cdef public OctObjectPool domains
cdef Oct ****root_mesh
cdef int partial_coverage
cdef int level_offset
diff -r b9e3cef0f25a25b6bbb94aaa24d7d36a796b56e0 -r 38d949eddcf0942047812c03a2974dc72a832667 yt/geometry/oct_container.pyx
--- a/yt/geometry/oct_container.pyx
+++ b/yt/geometry/oct_container.pyx
@@ -92,7 +92,7 @@
self.nn[i] = oct_domain_dimensions[i]
self.num_domains = 0
self.level_offset = 0
- self.domains = NULL
+ self.domains = OctObjectPool()
p = 0
self.nocts = 0 # Increment when initialized
for i in range(3):
@@ -112,16 +112,7 @@
@property
def oct_arrays(self):
- cdef OctAllocationContainer *cur = self.cont
- cdef Oct *this
- cdef int i
- cdef OctPadded[:] mm
- rv = []
- while cur != NULL:
- mm = <OctPadded[:cur.n_assigned]> (<OctPadded*> cur.my_octs)
- rv.append(np.asarray(mm))
- cur = cur.next
- return rv
+ return self.domains.to_arrays()
@classmethod
def load_octree(cls, header):
@@ -148,11 +139,11 @@
for i in range(3):
dds[i] = (obj.DRE[i] - obj.DLE[i]) / obj.nn[i]
# Pos is the center of the octs
- cdef OctAllocationContainer *cur = obj.domains[0]
+ cdef AllocationContainer *cur = &obj.domains.containers[0]
cdef Oct *o
- cdef np.int64_t nfinest = 0
+ cdef np.uint64_t nfinest = 0
visitor.ref_mask = ref_mask
- visitor.octs = cur.my_octs
+ visitor.octs = <Oct *> cur.my_objs
visitor.nocts = &cur.n_assigned
visitor.nfinest = &nfinest
pos[0] = obj.DLE[0] + dds[0]/2.0
@@ -163,7 +154,7 @@
for k in range(obj.nn[2]):
if obj.root_mesh[i][j][k] != NULL:
raise RuntimeError
- o = &cur.my_octs[cur.n_assigned]
+ o = &((<Oct *> cur.my_objs)[cur.n_assigned])
o.domain_ind = o.file_ind = 0
o.domain = 1
obj.root_mesh[i][j][k] = o
@@ -196,19 +187,6 @@
free(self.root_mesh[i])
free(self.root_mesh)
- def __iter__(self):
- #Get the next oct, will traverse domains
- #Note that oct containers can be sorted
- #so that consecutive octs are on the same domain
- cdef OctAllocationContainer *cur = self.cont
- cdef Oct *this
- cdef int i
- while cur != NULL:
- for i in range(cur.n_assigned):
- this = &cur.my_octs[i]
- yield (this.file_ind, this.domain_ind, this.domain)
- cur = cur.next
-
@cython.cdivision(True)
cdef void visit_all_octs(self, SelectorObject selector,
OctVisitor visitor, int vc = -1):
@@ -649,7 +627,7 @@
cdef np.float64_t dds[3]
no = pos.shape[0] #number of octs
if curdom > self.num_domains: return 0
- cdef OctAllocationContainer *cont = self.domains[curdom - 1]
+ cdef AllocationContainer *cont = &self.domains.containers[curdom - 1]
cdef int initial = cont.n_assigned
cdef int in_boundary = 0
# How do we bootstrap ourselves?
@@ -695,32 +673,19 @@
cdef OctAllocationContainer *cur = self.cont
assert(cur == NULL)
self.num_domains = len(domain_counts) # 1-indexed
- self.domains = <OctAllocationContainer **> malloc(
- sizeof(OctAllocationContainer *) * len(domain_counts))
for i, count in enumerate(domain_counts):
- cur = allocate_octs(count, cur)
- if self.cont == NULL: self.cont = cur
- self.domains[i] = cur
+ self.domains.append(count)
cdef void append_domain(self, np.int64_t domain_count):
self.num_domains += 1
- self.domains = <OctAllocationContainer **> realloc(self.domains,
- sizeof(OctAllocationContainer *) * self.num_domains)
- if self.domains == NULL: raise RuntimeError
- self.domains[self.num_domains - 1] = NULL
- cdef OctAllocationContainer *cur = NULL
- if self.num_domains > 1:
- cur = self.domains[self.num_domains - 2]
- cur = allocate_octs(domain_count, cur)
- if self.cont == NULL: self.cont = cur
- self.domains[self.num_domains - 1] = cur
+ self.domains.append(domain_count)
cdef Oct* next_root(self, int domain_id, int ind[3]):
cdef Oct *next = self.root_mesh[ind[0]][ind[1]][ind[2]]
if next != NULL: return next
- cdef OctAllocationContainer *cont = self.domains[domain_id - 1]
+ cdef AllocationContainer *cont = &self.domains.containers[domain_id - 1]
if cont.n_assigned >= cont.n: raise RuntimeError
- next = &cont.my_octs[cont.n_assigned]
+ next = &((<Oct *> cont.my_objs)[cont.n_assigned])
cont.n_assigned += 1
self.root_mesh[ind[0]][ind[1]][ind[2]] = next
self.nocts += 1
@@ -737,9 +702,9 @@
for i in range(8):
parent.children[i] = NULL
if next != NULL: return next
- cdef OctAllocationContainer *cont = self.domains[domain_id - 1]
+ cdef AllocationContainer *cont = &self.domains.containers[domain_id - 1]
if cont.n_assigned >= cont.n: raise RuntimeError
- next = &cont.my_octs[cont.n_assigned]
+ next = &((<Oct *> cont.my_objs)[cont.n_assigned])
cont.n_assigned += 1
parent.children[cind(ind[0],ind[1],ind[2])] = next
self.nocts += 1
@@ -931,14 +896,14 @@
cdef Oct *next = NULL
self.get_root(ind, &next)
if next != NULL: return next
- cdef OctAllocationContainer *cont = self.domains[domain_id - 1]
+ cdef AllocationContainer *cont = &self.domains.containers[domain_id - 1]
if cont.n_assigned >= cont.n:
print "Too many assigned."
return NULL
if self.num_root >= self.max_root:
print "Too many roots."
return NULL
- next = &cont.my_octs[cont.n_assigned]
+ next = &((<Oct *> cont.my_objs)[cont.n_assigned])
cont.n_assigned += 1
cdef np.int64_t key = 0
cdef OctKey *ikey = &self.root_nodes[self.num_root]
@@ -963,7 +928,6 @@
# This gets called BEFORE the superclass deallocation. But, both get
# called.
if self.root_nodes != NULL: free(self.root_nodes)
- if self.domains != NULL: free(self.domains)
cdef class RAMSESOctreeContainer(SparseOctreeContainer):
pass
@@ -1060,7 +1024,7 @@
cdef np.uint64_t i
cdef Oct* octs = <Oct *> obj
for n in range(n):
- octs[n].file_ind = oct.domain = - 1
+ octs[n].file_ind = octs[n].domain = - 1
octs[n].domain_ind = n + offset
octs[n].children = NULL
@@ -1075,6 +1039,8 @@
def _con_to_array(self, int i):
cdef AllocationContainer *obj = &self.containers[i]
+ if obj.n_assigned == 0:
+ return None
cdef OctPadded[:] mm = <OctPadded[:obj.n_assigned]> (
<OctPadded*> obj.my_objs)
rv = np.asarray(mm)
diff -r b9e3cef0f25a25b6bbb94aaa24d7d36a796b56e0 -r 38d949eddcf0942047812c03a2974dc72a832667 yt/geometry/oct_visitors.pxd
--- a/yt/geometry/oct_visitors.pxd
+++ b/yt/geometry/oct_visitors.pxd
@@ -117,8 +117,8 @@
cdef class LoadOctree(OctVisitor):
cdef np.uint8_t[:] ref_mask
cdef Oct* octs
- cdef np.int64_t *nocts
- cdef np.int64_t *nfinest
+ cdef np.uint64_t *nocts
+ cdef np.uint64_t *nfinest
cdef inline int cind(int i, int j, int k):
# THIS ONLY WORKS FOR CHILDREN. It is not general for zones.
https://bitbucket.org/yt_analysis/yt/commits/f2094cf8a272/
Changeset: f2094cf8a272
Branch: yt
User: MatthewTurk
Date: 2016-11-28 19:54:06+00:00
Summary: Removing all OctAllocationContainer objects
Affected #: 7 files
diff -r 38d949eddcf0942047812c03a2974dc72a832667 -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 yt/geometry/oct_container.pxd
--- a/yt/geometry/oct_container.pxd
+++ b/yt/geometry/oct_container.pxd
@@ -37,15 +37,6 @@
np.int64_t ipos[3]
np.int32_t level
-cdef struct OctAllocationContainer
-cdef struct OctAllocationContainer:
- np.int64_t n
- np.int64_t n_assigned
- np.int64_t offset
- np.int64_t con_id
- OctAllocationContainer *next
- Oct *my_octs
-
cdef struct OctList
cdef struct OctList:
@@ -60,7 +51,6 @@
cdef void OctList_delete(OctList *list)
cdef class OctreeContainer:
- cdef OctAllocationContainer *cont
cdef public OctObjectPool domains
cdef Oct ****root_mesh
cdef int partial_coverage
@@ -78,7 +68,7 @@
Oct *o, bint periodicity[3])
cdef void oct_bounds(self, Oct *, np.float64_t *, np.float64_t *)
# This function must return the offset from global-to-local domains; i.e.,
- # OctAllocationContainer.offset if such a thing exists.
+ # AllocationContainer.offset if such a thing exists.
cdef np.int64_t get_domain_offset(self, int domain_id)
cdef void visit_all_octs(self,
selection_routines.SelectorObject selector,
diff -r 38d949eddcf0942047812c03a2974dc72a832667 -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 yt/geometry/oct_container.pyx
--- a/yt/geometry/oct_container.pyx
+++ b/yt/geometry/oct_container.pyx
@@ -29,52 +29,13 @@
# NOTE that size_t might not be int
void *alloca(int)
-cdef OctAllocationContainer *allocate_octs(
- int n_octs, OctAllocationContainer *prev):
- cdef OctAllocationContainer *n_cont
- cdef Oct *oct
- cdef int n, i, j, k
- n_cont = <OctAllocationContainer *> malloc(
- sizeof(OctAllocationContainer))
- if prev == NULL:
- n_cont.offset = 0
- else:
- n_cont.offset = prev.offset + prev.n
- n_cont.my_octs = <Oct *> malloc(sizeof(Oct) * n_octs)
- if n_cont.my_octs == NULL:
- raise MemoryError
- n_cont.n = n_octs
- n_cont.n_assigned = 0
- n_cont.con_id = -1
- for n in range(n_octs):
- oct = &n_cont.my_octs[n]
- oct.file_ind = oct.domain = -1
- oct.domain_ind = n + n_cont.offset
- oct.children = NULL
- if prev != NULL:
- prev.next = n_cont
- n_cont.next = NULL
- return n_cont
-
-cdef void free_octs(
- OctAllocationContainer *first):
- cdef OctAllocationContainer *cur
- while first != NULL:
- cur = first
- for i in range(cur.n):
- if cur.my_octs[i].children != NULL:
- free(cur.my_octs[i].children)
- free(first.my_octs)
- first = cur.next
- free(cur)
-
# Here is the strategy for RAMSES containers:
# * Read each domain individually, creating *all* octs found in that domain
# file, even if they reside on other CPUs.
# * Only allocate octs that reside on >= domain
# * For all octs, insert into tree, which may require traversing existing
# octs
-# * Note that this does not allow OctAllocationContainer to exactly be a
+# * Note that this does not allow AllocationContainer to exactly be a
# chunk, but it is close. For IO chunking, we can theoretically examine
# those octs that live inside a given allocator.
@@ -86,7 +47,6 @@
# This will just initialize the root mesh octs
self.oref = over_refine
self.partial_coverage = partial_coverage
- self.cont = NULL
cdef int i, j, k, p
for i in range(3):
self.nn[i] = oct_domain_dimensions[i]
@@ -176,7 +136,6 @@
return obj
def __dealloc__(self):
- free_octs(self.cont)
if self.root_mesh == NULL: return
for i in range(self.nn[0]):
if self.root_mesh[i] == NULL: continue
@@ -670,8 +629,6 @@
def allocate_domains(self, domain_counts):
cdef int count, i
- cdef OctAllocationContainer *cur = self.cont
- assert(cur == NULL)
self.num_domains = len(domain_counts) # 1-indexed
for i, count in enumerate(domain_counts):
self.domains.append(count)
diff -r 38d949eddcf0942047812c03a2974dc72a832667 -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 yt/geometry/particle_deposit.pxd
--- a/yt/geometry/particle_deposit.pxd
+++ b/yt/geometry/particle_deposit.pxd
@@ -21,7 +21,7 @@
from libc.math cimport sqrt
from yt.utilities.lib.fp_utils cimport *
-from .oct_container cimport Oct, OctAllocationContainer, OctreeContainer
+from .oct_container cimport Oct, OctreeContainer
cdef extern from "platform_dep.h":
void *alloca(int)
diff -r 38d949eddcf0942047812c03a2974dc72a832667 -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 yt/geometry/particle_deposit.pyx
--- a/yt/geometry/particle_deposit.pyx
+++ b/yt/geometry/particle_deposit.pyx
@@ -22,8 +22,8 @@
from cpython cimport PyObject
from yt.utilities.lib.fp_utils cimport *
-from oct_container cimport Oct, OctAllocationContainer, \
- OctreeContainer, OctInfo
+from oct_container cimport \
+ Oct, OctreeContainer, OctInfo
from cpython.array cimport array, clone
from cython.view cimport memoryview as cymemview
from yt.utilities.lib.misc_utilities import OnceIndirect
diff -r 38d949eddcf0942047812c03a2974dc72a832667 -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 yt/geometry/particle_smooth.pxd
--- a/yt/geometry/particle_smooth.pxd
+++ b/yt/geometry/particle_smooth.pxd
@@ -21,7 +21,7 @@
from libc.math cimport sqrt
from yt.utilities.lib.fp_utils cimport *
-from oct_container cimport Oct, OctAllocationContainer, OctreeContainer
+from oct_container cimport Oct, OctreeContainer
from .particle_deposit cimport kernel_func, get_kernel_func, gind
from yt.utilities.lib.distance_queue cimport NeighborList, Neighbor_compare, \
r2dist, DistanceQueue
diff -r 38d949eddcf0942047812c03a2974dc72a832667 -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 yt/geometry/particle_smooth.pyx
--- a/yt/geometry/particle_smooth.pyx
+++ b/yt/geometry/particle_smooth.pyx
@@ -21,8 +21,8 @@
cimport cython
from libc.math cimport sqrt, fabs, sin, cos
-from oct_container cimport Oct, OctAllocationContainer, \
- OctreeContainer, OctInfo
+from oct_container cimport \
+ Oct, OctreeContainer, OctInfo
cdef void spherical_coord_setup(np.float64_t ipos[3], np.float64_t opos[3]):
diff -r 38d949eddcf0942047812c03a2974dc72a832667 -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 yt/geometry/selection_routines.pyx
--- a/yt/geometry/selection_routines.pyx
+++ b/yt/geometry/selection_routines.pyx
@@ -19,7 +19,7 @@
cimport cython
from libc.stdlib cimport malloc, free
from yt.utilities.lib.fp_utils cimport fclip, iclip, fmax, fmin, imin, imax
-from .oct_container cimport OctreeContainer, OctAllocationContainer, Oct
+from .oct_container cimport OctreeContainer, Oct
cimport oct_visitors
from .oct_visitors cimport cind
from yt.utilities.lib.volume_container cimport \
https://bitbucket.org/yt_analysis/yt/commits/c21e07cb268e/
Changeset: c21e07cb268e
Branch: yt
User: MatthewTurk
Date: 2016-11-29 19:47:41+00:00
Summary: Adding docstrings
Affected #: 4 files
diff -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 -r c21e07cb268ea0b59db0b691a8996f57216b05df yt/frontends/artio/_artio_caller.pyx
--- a/yt/frontends/artio/_artio_caller.pyx
+++ b/yt/frontends/artio/_artio_caller.pyx
@@ -15,8 +15,6 @@
from libc.string cimport memcpy
import data_structures
from yt.utilities.lib.misc_utilities import OnceIndirect
-from yt.utilities.lib.allocation_container cimport \
- AllocationContainer
cdef extern from "platform_dep.h":
ctypedef int int32_t
diff -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 -r c21e07cb268ea0b59db0b691a8996f57216b05df yt/geometry/oct_container.pxd
--- a/yt/geometry/oct_container.pxd
+++ b/yt/geometry/oct_container.pxd
@@ -43,8 +43,18 @@
OctList *next
Oct *o
+# NOTE: This object *has* to be the same size as the AllocationContainer
+# object. There's an assert in the __cinit__ function.
+cdef struct OctAllocationContainer:
+ np.uint64_t n
+ np.uint64_t n_assigned
+ np.uint64_t offset
+ np.int64_t con_id # container id
+ Oct *my_objs
+
cdef class OctObjectPool(ObjectPool):
- pass
+ cdef inline OctAllocationContainer *get_cont(self, int i):
+ return <OctAllocationContainer*> (&self.containers[i])
cdef OctList *OctList_append(OctList *list, Oct *o)
cdef int OctList_count(OctList *list)
diff -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 -r c21e07cb268ea0b59db0b691a8996f57216b05df yt/geometry/oct_container.pyx
--- a/yt/geometry/oct_container.pyx
+++ b/yt/geometry/oct_container.pyx
@@ -35,9 +35,10 @@
# * Only allocate octs that reside on >= domain
# * For all octs, insert into tree, which may require traversing existing
# octs
-# * Note that this does not allow AllocationContainer to exactly be a
-# chunk, but it is close. For IO chunking, we can theoretically examine
-# those octs that live inside a given allocator.
+# * Note that this does not allow one component of an ObjectPool (an
+# AllocationContainer) to exactly be a chunk, but it is close. For IO
+# chunking, we can theoretically examine those octs that live inside a
+# given allocator.
cdef class OctreeContainer:
@@ -99,11 +100,11 @@
for i in range(3):
dds[i] = (obj.DRE[i] - obj.DLE[i]) / obj.nn[i]
# Pos is the center of the octs
- cdef AllocationContainer *cur = &obj.domains.containers[0]
+ cdef OctAllocationContainer *cur = obj.domains.get_cont(0)
cdef Oct *o
cdef np.uint64_t nfinest = 0
visitor.ref_mask = ref_mask
- visitor.octs = <Oct *> cur.my_objs
+ visitor.octs = cur.my_objs
visitor.nocts = &cur.n_assigned
visitor.nfinest = &nfinest
pos[0] = obj.DLE[0] + dds[0]/2.0
@@ -114,7 +115,7 @@
for k in range(obj.nn[2]):
if obj.root_mesh[i][j][k] != NULL:
raise RuntimeError
- o = &((<Oct *> cur.my_objs)[cur.n_assigned])
+ o = &cur.my_objs[cur.n_assigned]
o.domain_ind = o.file_ind = 0
o.domain = 1
obj.root_mesh[i][j][k] = o
@@ -586,7 +587,7 @@
cdef np.float64_t dds[3]
no = pos.shape[0] #number of octs
if curdom > self.num_domains: return 0
- cdef AllocationContainer *cont = &self.domains.containers[curdom - 1]
+ cdef OctAllocationContainer *cont = self.domains.get_cont(curdom - 1)
cdef int initial = cont.n_assigned
cdef int in_boundary = 0
# How do we bootstrap ourselves?
@@ -640,9 +641,9 @@
cdef Oct* next_root(self, int domain_id, int ind[3]):
cdef Oct *next = self.root_mesh[ind[0]][ind[1]][ind[2]]
if next != NULL: return next
- cdef AllocationContainer *cont = &self.domains.containers[domain_id - 1]
+ cdef OctAllocationContainer *cont = self.domains.get_cont(domain_id - 1)
if cont.n_assigned >= cont.n: raise RuntimeError
- next = &((<Oct *> cont.my_objs)[cont.n_assigned])
+ next = &cont.my_objs[cont.n_assigned]
cont.n_assigned += 1
self.root_mesh[ind[0]][ind[1]][ind[2]] = next
self.nocts += 1
@@ -659,9 +660,9 @@
for i in range(8):
parent.children[i] = NULL
if next != NULL: return next
- cdef AllocationContainer *cont = &self.domains.containers[domain_id - 1]
+ cdef OctAllocationContainer *cont = self.domains.get_cont(domain_id - 1)
if cont.n_assigned >= cont.n: raise RuntimeError
- next = &((<Oct *> cont.my_objs)[cont.n_assigned])
+ next = &cont.my_objs[cont.n_assigned]
cont.n_assigned += 1
parent.children[cind(ind[0],ind[1],ind[2])] = next
self.nocts += 1
@@ -853,14 +854,14 @@
cdef Oct *next = NULL
self.get_root(ind, &next)
if next != NULL: return next
- cdef AllocationContainer *cont = &self.domains.containers[domain_id - 1]
+ cdef OctAllocationContainer *cont = self.domains.get_cont(domain_id - 1)
if cont.n_assigned >= cont.n:
print "Too many assigned."
return NULL
if self.num_root >= self.max_root:
print "Too many roots."
return NULL
- next = &((<Oct *> cont.my_objs)[cont.n_assigned])
+ next = &cont.my_objs[cont.n_assigned]
cont.n_assigned += 1
cdef np.int64_t key = 0
cdef OctKey *ikey = &self.root_nodes[self.num_root]
@@ -972,9 +973,15 @@
this = next
cdef class OctObjectPool(ObjectPool):
+ # This is an inherited version of the ObjectPool that provides setup and
+ # teardown functions for the individually allocated objects. These allow
+ # us to initialize the Octs to default values, and we can also free any
+ # allocated memory in them. Implementing _con_to_array also provides the
+ # opportunity to supply views of the octs in Python code.
def __cinit__(self):
# Base class will ALSO be called
self.itemsize = sizeof(Oct)
+ assert(sizeof(OctAllocationContainer) == sizeof(AllocationContainer))
cdef void setup_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
np.int64_t con_id):
diff -r f2094cf8a27203ee52043e3a547c5d28cbc994e4 -r c21e07cb268ea0b59db0b691a8996f57216b05df yt/utilities/lib/allocation_container.pyx
--- a/yt/utilities/lib/allocation_container.pyx
+++ b/yt/utilities/lib/allocation_container.pyx
@@ -18,6 +18,11 @@
cdef class ObjectPool:
def __cinit__(self):
+ """This class is *not* meant to be initialized directly, but instead
+ through subclasses. Those subclasses need to implement at a minimum
+ the setting of itemsize, but can optionally also implement setup_objs
+ and teardown_objs to either set default values or initialize additional
+ pointers and values, and then free them."""
self.containers = NULL
self.n_con = 0
self.itemsize = -1 # Never use the base class
@@ -32,12 +37,16 @@
free(self.containers)
def __getitem__(self, int i):
+ """This returns an array view (if possible and implemented in a
+ subclass) on the pool of objects specified by i."""
return self._con_to_array(i)
def __len__(self):
return self.n_con
def append(self, int n_objs, np.int64_t con_id = -1):
+ """This allocates a new batch of n_objs objects, with the container id
+ specified as con_id. Return value is a view on them."""
self.allocate_objs(n_objs, con_id)
return self[self.n_con - 1]
@@ -64,13 +73,18 @@
obj = <char*> n_cont.my_objs
self.setup_objs(n_cont.my_objs, n_objs, n_cont.offset, n_cont.con_id)
- cdef void setup_objs(self, void *obj, np.uint64_t count, np.uint64_t
- offset, np.int64_t con_id):
+ cdef void setup_objs(self, void *obj, np.uint64_t count,
+ np.uint64_t offset, np.int64_t con_id):
+ """This can be overridden in the subclass, where it can initialize any
+ of the allocated objects."""
pass
cdef void teardown_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
np.int64_t con_id):
# We assume that these are all allocated and have no sub-allocations
+ """If overridden, additional behavior can be provided during teardown
+ of allocations. For instance, if you allocate some memory on each of
+ the allocated objects."""
if obj != NULL:
free(obj)
@@ -82,10 +96,16 @@
return rv
def _con_to_array(self, int i):
+ """This has to be implemented in a subclass, and should return an
+ appropriate np.asarray() of a memoryview of self.my_objs."""
raise NotImplementedError
cdef class BitmaskPool(ObjectPool):
def __cinit__(self):
+ """This is an example implementation of object pools for bitmasks
+ (uint8) arrays. It lets you reasonably quickly allocate a set of
+ uint8 arrays which can be accessed and modified, and then virtually
+ append to that."""
# Base class will ALSO be called
self.itemsize = sizeof(np.uint8_t)
https://bitbucket.org/yt_analysis/yt/commits/95ee1bbc1c01/
Changeset: 95ee1bbc1c01
Branch: yt
User: MatthewTurk
Date: 2016-11-29 19:50:48+00:00
Summary: Adding self.domains initialization to SparseOctree
Affected #: 1 file
diff -r c21e07cb268ea0b59db0b691a8996f57216b05df -r 95ee1bbc1c01bd7fe6fd1a97ce6215147c0730ad yt/geometry/oct_container.pyx
--- a/yt/geometry/oct_container.pyx
+++ b/yt/geometry/oct_container.pyx
@@ -765,6 +765,7 @@
self.oref = over_refine
for i in range(3):
self.nn[i] = domain_dimensions[i]
+ self.domains = OctObjectPool()
self.num_domains = 0
self.level_offset = 0
self.nocts = 0 # Increment when initialized
https://bitbucket.org/yt_analysis/yt/commits/68cdeca5910d/
Changeset: 68cdeca5910d
Branch: yt
User: xarthisius
Date: 2016-12-06 16:22:23+00:00
Summary: Merged in MatthewTurk/yt (pull request #2446)
Adding Object Pool
Affected #: 13 files
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 setup.py
--- a/setup.py
+++ b/setup.py
@@ -180,7 +180,7 @@
"particle_mesh_operations", "depth_first_octree", "fortran_reader",
"interpolators", "misc_utilities", "basic_octree", "image_utilities",
"points_in_volume", "quad_tree", "ray_integrators", "mesh_utilities",
- "amr_kdtools", "lenses", "distance_queue"
+ "amr_kdtools", "lenses", "distance_queue", "allocation_container"
]
for ext_name in lib_exts:
cython_extensions.append(
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/frontends/artio/_artio_caller.pyx
--- a/yt/frontends/artio/_artio_caller.pyx
+++ b/yt/frontends/artio/_artio_caller.pyx
@@ -7,7 +7,7 @@
SelectorObject, AlwaysSelector, OctreeSubsetSelector
from yt.utilities.lib.fp_utils cimport imax
from yt.geometry.oct_container cimport \
- SparseOctreeContainer
+ SparseOctreeContainer, OctObjectPool
from yt.geometry.oct_visitors cimport Oct
from yt.geometry.particle_deposit cimport \
ParticleDepositOperation
@@ -923,7 +923,7 @@
super(ARTIOOctreeContainer, self).__init__(dims, DLE, DRE)
self.artio_handle = range_handler.artio_handle
self.level_offset = 1
- self.domains = NULL
+ self.domains = OctObjectPool()
self.root_nodes = NULL
@cython.boundscheck(False)
@@ -949,7 +949,7 @@
# We only allow one root oct.
self.append_domain(oct_count)
- self.domains[self.num_domains - 1].con_id = sfc
+ self.domains.containers[self.num_domains - 1].con_id = sfc
oct_ind = -1
ipos = 0
@@ -1009,7 +1009,7 @@
source_arrays = []
ipos = -1
for i in range(self.num_domains):
- ipos = imax(ipos, self.domains[i].n)
+ ipos = imax(ipos, self.domains.containers[i].n)
for i in range(nf):
field_ind[i] = field_indices[i]
# Note that we subtract one, because we're not using the root mesh.
@@ -1029,13 +1029,13 @@
# double-loop to calculate domain_counts
# The cons should be in order
cdef np.int64_t sfc_start, sfc_end
- sfc_start = self.domains[0].con_id
- sfc_end = self.domains[self.num_domains - 1].con_id
+ sfc_start = self.domains.containers[0].con_id
+ sfc_end = self.domains.containers[self.num_domains - 1].con_id
status = artio_grid_cache_sfc_range(handle, sfc_start, sfc_end)
check_artio_status(status)
cdef np.int64_t offset = 0
for si in range(self.num_domains):
- sfc = self.domains[si].con_id
+ sfc = self.domains.containers[si].con_id
status = artio_grid_read_root_cell_begin( handle, sfc,
dpos, NULL, &num_oct_levels, num_octs_per_level)
check_artio_status(status)
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/geometry/oct_container.pxd
--- a/yt/geometry/oct_container.pxd
+++ b/yt/geometry/oct_container.pxd
@@ -22,6 +22,8 @@
from .oct_visitors cimport OctVisitor, Oct, cind
from libc.stdlib cimport bsearch, qsort, realloc, malloc, free
from libc.math cimport floor
+from yt.utilities.lib.allocation_container cimport \
+ ObjectPool, AllocationContainer
cdef int ORDER_MAX
@@ -35,28 +37,31 @@
np.int64_t ipos[3]
np.int32_t level
-cdef struct OctAllocationContainer
-cdef struct OctAllocationContainer:
- np.int64_t n
- np.int64_t n_assigned
- np.int64_t offset
- np.int64_t con_id
- OctAllocationContainer *next
- Oct *my_octs
-
cdef struct OctList
cdef struct OctList:
OctList *next
Oct *o
+# NOTE: This object *has* to be the same size as the AllocationContainer
+# object. There's an assert in the __cinit__ function.
+cdef struct OctAllocationContainer:
+ np.uint64_t n
+ np.uint64_t n_assigned
+ np.uint64_t offset
+ np.int64_t con_id # container id
+ Oct *my_objs
+
+cdef class OctObjectPool(ObjectPool):
+ cdef inline OctAllocationContainer *get_cont(self, int i):
+ return <OctAllocationContainer*> (&self.containers[i])
+
cdef OctList *OctList_append(OctList *list, Oct *o)
cdef int OctList_count(OctList *list)
cdef void OctList_delete(OctList *list)
cdef class OctreeContainer:
- cdef OctAllocationContainer *cont
- cdef OctAllocationContainer **domains
+ cdef public OctObjectPool domains
cdef Oct ****root_mesh
cdef int partial_coverage
cdef int level_offset
@@ -73,7 +78,7 @@
Oct *o, bint periodicity[3])
cdef void oct_bounds(self, Oct *, np.float64_t *, np.float64_t *)
# This function must return the offset from global-to-local domains; i.e.,
- # OctAllocationContainer.offset if such a thing exists.
+ # AllocationContainer.offset if such a thing exists.
cdef np.int64_t get_domain_offset(self, int domain_id)
cdef void visit_all_octs(self,
selection_routines.SelectorObject selector,
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/geometry/oct_container.pyx
--- a/yt/geometry/oct_container.pyx
+++ b/yt/geometry/oct_container.pyx
@@ -29,54 +29,16 @@
# NOTE that size_t might not be int
void *alloca(int)
-cdef OctAllocationContainer *allocate_octs(
- int n_octs, OctAllocationContainer *prev):
- cdef OctAllocationContainer *n_cont
- cdef Oct *oct
- cdef int n, i, j, k
- n_cont = <OctAllocationContainer *> malloc(
- sizeof(OctAllocationContainer))
- if prev == NULL:
- n_cont.offset = 0
- else:
- n_cont.offset = prev.offset + prev.n
- n_cont.my_octs = <Oct *> malloc(sizeof(Oct) * n_octs)
- if n_cont.my_octs == NULL:
- raise MemoryError
- n_cont.n = n_octs
- n_cont.n_assigned = 0
- n_cont.con_id = -1
- for n in range(n_octs):
- oct = &n_cont.my_octs[n]
- oct.file_ind = oct.domain = -1
- oct.domain_ind = n + n_cont.offset
- oct.children = NULL
- if prev != NULL:
- prev.next = n_cont
- n_cont.next = NULL
- return n_cont
-
-cdef void free_octs(
- OctAllocationContainer *first):
- cdef OctAllocationContainer *cur
- while first != NULL:
- cur = first
- for i in range(cur.n):
- if cur.my_octs[i].children != NULL:
- free(cur.my_octs[i].children)
- free(first.my_octs)
- first = cur.next
- free(cur)
-
# Here is the strategy for RAMSES containers:
# * Read each domain individually, creating *all* octs found in that domain
# file, even if they reside on other CPUs.
# * Only allocate octs that reside on >= domain
# * For all octs, insert into tree, which may require traversing existing
# octs
-# * Note that this does not allow OctAllocationContainer to exactly be a
-# chunk, but it is close. For IO chunking, we can theoretically examine
-# those octs that live inside a given allocator.
+# * Note that this does not allow one component of an ObjectPool (an
+# AllocationContainer) to exactly be a chunk, but it is close. For IO
+# chunking, we can theoretically examine those octs that live inside a
+# given allocator.
cdef class OctreeContainer:
@@ -86,13 +48,12 @@
# This will just initialize the root mesh octs
self.oref = over_refine
self.partial_coverage = partial_coverage
- self.cont = NULL
cdef int i, j, k, p
for i in range(3):
self.nn[i] = oct_domain_dimensions[i]
self.num_domains = 0
self.level_offset = 0
- self.domains = NULL
+ self.domains = OctObjectPool()
p = 0
self.nocts = 0 # Increment when initialized
for i in range(3):
@@ -112,16 +73,7 @@
@property
def oct_arrays(self):
- cdef OctAllocationContainer *cur = self.cont
- cdef Oct *this
- cdef int i
- cdef OctPadded[:] mm
- rv = []
- while cur != NULL:
- mm = <OctPadded[:cur.n_assigned]> (<OctPadded*> cur.my_octs)
- rv.append(np.asarray(mm))
- cur = cur.next
- return rv
+ return self.domains.to_arrays()
@classmethod
def load_octree(cls, header):
@@ -148,11 +100,11 @@
for i in range(3):
dds[i] = (obj.DRE[i] - obj.DLE[i]) / obj.nn[i]
# Pos is the center of the octs
- cdef OctAllocationContainer *cur = obj.domains[0]
+ cdef OctAllocationContainer *cur = obj.domains.get_cont(0)
cdef Oct *o
- cdef np.int64_t nfinest = 0
+ cdef np.uint64_t nfinest = 0
visitor.ref_mask = ref_mask
- visitor.octs = cur.my_octs
+ visitor.octs = cur.my_objs
visitor.nocts = &cur.n_assigned
visitor.nfinest = &nfinest
pos[0] = obj.DLE[0] + dds[0]/2.0
@@ -163,7 +115,7 @@
for k in range(obj.nn[2]):
if obj.root_mesh[i][j][k] != NULL:
raise RuntimeError
- o = &cur.my_octs[cur.n_assigned]
+ o = &cur.my_objs[cur.n_assigned]
o.domain_ind = o.file_ind = 0
o.domain = 1
obj.root_mesh[i][j][k] = o
@@ -185,7 +137,6 @@
return obj
def __dealloc__(self):
- free_octs(self.cont)
if self.root_mesh == NULL: return
for i in range(self.nn[0]):
if self.root_mesh[i] == NULL: continue
@@ -196,19 +147,6 @@
free(self.root_mesh[i])
free(self.root_mesh)
- def __iter__(self):
- #Get the next oct, will traverse domains
- #Note that oct containers can be sorted
- #so that consecutive octs are on the same domain
- cdef OctAllocationContainer *cur = self.cont
- cdef Oct *this
- cdef int i
- while cur != NULL:
- for i in range(cur.n_assigned):
- this = &cur.my_octs[i]
- yield (this.file_ind, this.domain_ind, this.domain)
- cur = cur.next
-
@cython.cdivision(True)
cdef void visit_all_octs(self, SelectorObject selector,
OctVisitor visitor, int vc = -1):
@@ -649,7 +587,7 @@
cdef np.float64_t dds[3]
no = pos.shape[0] #number of octs
if curdom > self.num_domains: return 0
- cdef OctAllocationContainer *cont = self.domains[curdom - 1]
+ cdef OctAllocationContainer *cont = self.domains.get_cont(curdom - 1)
cdef int initial = cont.n_assigned
cdef int in_boundary = 0
# How do we bootstrap ourselves?
@@ -692,35 +630,20 @@
def allocate_domains(self, domain_counts):
cdef int count, i
- cdef OctAllocationContainer *cur = self.cont
- assert(cur == NULL)
self.num_domains = len(domain_counts) # 1-indexed
- self.domains = <OctAllocationContainer **> malloc(
- sizeof(OctAllocationContainer *) * len(domain_counts))
for i, count in enumerate(domain_counts):
- cur = allocate_octs(count, cur)
- if self.cont == NULL: self.cont = cur
- self.domains[i] = cur
+ self.domains.append(count)
cdef void append_domain(self, np.int64_t domain_count):
self.num_domains += 1
- self.domains = <OctAllocationContainer **> realloc(self.domains,
- sizeof(OctAllocationContainer *) * self.num_domains)
- if self.domains == NULL: raise RuntimeError
- self.domains[self.num_domains - 1] = NULL
- cdef OctAllocationContainer *cur = NULL
- if self.num_domains > 1:
- cur = self.domains[self.num_domains - 2]
- cur = allocate_octs(domain_count, cur)
- if self.cont == NULL: self.cont = cur
- self.domains[self.num_domains - 1] = cur
+ self.domains.append(domain_count)
cdef Oct* next_root(self, int domain_id, int ind[3]):
cdef Oct *next = self.root_mesh[ind[0]][ind[1]][ind[2]]
if next != NULL: return next
- cdef OctAllocationContainer *cont = self.domains[domain_id - 1]
+ cdef OctAllocationContainer *cont = self.domains.get_cont(domain_id - 1)
if cont.n_assigned >= cont.n: raise RuntimeError
- next = &cont.my_octs[cont.n_assigned]
+ next = &cont.my_objs[cont.n_assigned]
cont.n_assigned += 1
self.root_mesh[ind[0]][ind[1]][ind[2]] = next
self.nocts += 1
@@ -737,9 +660,9 @@
for i in range(8):
parent.children[i] = NULL
if next != NULL: return next
- cdef OctAllocationContainer *cont = self.domains[domain_id - 1]
+ cdef OctAllocationContainer *cont = self.domains.get_cont(domain_id - 1)
if cont.n_assigned >= cont.n: raise RuntimeError
- next = &cont.my_octs[cont.n_assigned]
+ next = &cont.my_objs[cont.n_assigned]
cont.n_assigned += 1
parent.children[cind(ind[0],ind[1],ind[2])] = next
self.nocts += 1
@@ -842,6 +765,7 @@
self.oref = over_refine
for i in range(3):
self.nn[i] = domain_dimensions[i]
+ self.domains = OctObjectPool()
self.num_domains = 0
self.level_offset = 0
self.nocts = 0 # Increment when initialized
@@ -931,14 +855,14 @@
cdef Oct *next = NULL
self.get_root(ind, &next)
if next != NULL: return next
- cdef OctAllocationContainer *cont = self.domains[domain_id - 1]
+ cdef OctAllocationContainer *cont = self.domains.get_cont(domain_id - 1)
if cont.n_assigned >= cont.n:
print "Too many assigned."
return NULL
if self.num_root >= self.max_root:
print "Too many roots."
return NULL
- next = &cont.my_octs[cont.n_assigned]
+ next = &cont.my_objs[cont.n_assigned]
cont.n_assigned += 1
cdef np.int64_t key = 0
cdef OctKey *ikey = &self.root_nodes[self.num_root]
@@ -963,7 +887,6 @@
# This gets called BEFORE the superclass deallocation. But, both get
# called.
if self.root_nodes != NULL: free(self.root_nodes)
- if self.domains != NULL: free(self.domains)
cdef class RAMSESOctreeContainer(SparseOctreeContainer):
pass
@@ -1049,3 +972,41 @@
next = this.next
free(this)
this = next
+
+cdef class OctObjectPool(ObjectPool):
+ # This is an inherited version of the ObjectPool that provides setup and
+ # teardown functions for the individually allocated objects. These allow
+ # us to initialize the Octs to default values, and we can also free any
+ # allocated memory in them. Implementing _con_to_array also provides the
+ # opportunity to supply views of the octs in Python code.
+ def __cinit__(self):
+ # Base class will ALSO be called
+ self.itemsize = sizeof(Oct)
+ assert(sizeof(OctAllocationContainer) == sizeof(AllocationContainer))
+
+ cdef void setup_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
+ np.int64_t con_id):
+ cdef np.uint64_t i
+ cdef Oct* octs = <Oct *> obj
+ for n in range(n):
+ octs[n].file_ind = octs[n].domain = - 1
+ octs[n].domain_ind = n + offset
+ octs[n].children = NULL
+
+ cdef void teardown_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
+ np.int64_t con_id):
+ cdef np.uint64_t i, j
+ cdef Oct *my_octs = <Oct *> obj
+ for i in range(n):
+ if my_octs[i].children != NULL:
+ free(my_octs[i].children)
+ free(obj)
+
+ def _con_to_array(self, int i):
+ cdef AllocationContainer *obj = &self.containers[i]
+ if obj.n_assigned == 0:
+ return None
+ cdef OctPadded[:] mm = <OctPadded[:obj.n_assigned]> (
+ <OctPadded*> obj.my_objs)
+ rv = np.asarray(mm)
+ return rv
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/geometry/oct_visitors.pxd
--- a/yt/geometry/oct_visitors.pxd
+++ b/yt/geometry/oct_visitors.pxd
@@ -117,8 +117,8 @@
cdef class LoadOctree(OctVisitor):
cdef np.uint8_t[:] ref_mask
cdef Oct* octs
- cdef np.int64_t *nocts
- cdef np.int64_t *nfinest
+ cdef np.uint64_t *nocts
+ cdef np.uint64_t *nfinest
cdef inline int cind(int i, int j, int k):
# THIS ONLY WORKS FOR CHILDREN. It is not general for zones.
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/geometry/particle_deposit.pxd
--- a/yt/geometry/particle_deposit.pxd
+++ b/yt/geometry/particle_deposit.pxd
@@ -21,7 +21,7 @@
from libc.math cimport sqrt
from yt.utilities.lib.fp_utils cimport *
-from .oct_container cimport Oct, OctAllocationContainer, OctreeContainer
+from .oct_container cimport Oct, OctreeContainer
cdef extern from "platform_dep.h":
void *alloca(int)
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/geometry/particle_deposit.pyx
--- a/yt/geometry/particle_deposit.pyx
+++ b/yt/geometry/particle_deposit.pyx
@@ -22,8 +22,8 @@
from cpython cimport PyObject
from yt.utilities.lib.fp_utils cimport *
-from oct_container cimport Oct, OctAllocationContainer, \
- OctreeContainer, OctInfo
+from oct_container cimport \
+ Oct, OctreeContainer, OctInfo
from cpython.array cimport array, clone
from cython.view cimport memoryview as cymemview
from yt.utilities.lib.misc_utilities import OnceIndirect
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/geometry/particle_smooth.pxd
--- a/yt/geometry/particle_smooth.pxd
+++ b/yt/geometry/particle_smooth.pxd
@@ -21,7 +21,7 @@
from libc.math cimport sqrt
from yt.utilities.lib.fp_utils cimport *
-from oct_container cimport Oct, OctAllocationContainer, OctreeContainer
+from oct_container cimport Oct, OctreeContainer
from .particle_deposit cimport kernel_func, get_kernel_func, gind
from yt.utilities.lib.distance_queue cimport NeighborList, Neighbor_compare, \
r2dist, DistanceQueue
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/geometry/particle_smooth.pyx
--- a/yt/geometry/particle_smooth.pyx
+++ b/yt/geometry/particle_smooth.pyx
@@ -21,8 +21,8 @@
cimport cython
from libc.math cimport sqrt, fabs, sin, cos
-from oct_container cimport Oct, OctAllocationContainer, \
- OctreeContainer, OctInfo
+from oct_container cimport \
+ Oct, OctreeContainer, OctInfo
cdef void spherical_coord_setup(np.float64_t ipos[3], np.float64_t opos[3]):
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/geometry/selection_routines.pyx
--- a/yt/geometry/selection_routines.pyx
+++ b/yt/geometry/selection_routines.pyx
@@ -19,7 +19,7 @@
cimport cython
from libc.stdlib cimport malloc, free
from yt.utilities.lib.fp_utils cimport fclip, iclip, fmax, fmin, imin, imax
-from .oct_container cimport OctreeContainer, OctAllocationContainer, Oct
+from .oct_container cimport OctreeContainer, Oct
cimport oct_visitors
from .oct_visitors cimport cind
from yt.utilities.lib.volume_container cimport \
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/utilities/lib/allocation_container.pxd
--- /dev/null
+++ b/yt/utilities/lib/allocation_container.pxd
@@ -0,0 +1,35 @@
+"""
+An allocation container and memory pool
+
+
+
+"""
+
+#-----------------------------------------------------------------------------
+# Copyright (c) 2016, yt Development Team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file COPYING.txt, distributed with this software.
+#-----------------------------------------------------------------------------
+
+cimport numpy as np
+from libc.stdlib cimport malloc, free, realloc
+
+cdef struct AllocationContainer:
+ np.uint64_t n
+ np.uint64_t n_assigned
+ np.uint64_t offset
+ np.int64_t con_id # container id
+ void *my_objs
+
+cdef class ObjectPool:
+ cdef public np.uint64_t itemsize
+ cdef np.uint64_t n_con
+ cdef AllocationContainer* containers
+ cdef void allocate_objs(self, int n_objs, np.int64_t con_id = ?) except *
+ cdef void setup_objs(self, void *obj, np.uint64_t count,
+ np.uint64_t offset, np.int64_t con_id)
+ cdef void teardown_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
+ np.int64_t con_id)
+
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/utilities/lib/allocation_container.pyx
--- /dev/null
+++ b/yt/utilities/lib/allocation_container.pyx
@@ -0,0 +1,123 @@
+"""
+An allocation container and memory pool
+
+
+
+"""
+
+#-----------------------------------------------------------------------------
+# Copyright (c) 2016, yt Development Team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file COPYING.txt, distributed with this software.
+#-----------------------------------------------------------------------------
+
+cimport numpy as np
+import numpy as np
+
+cdef class ObjectPool:
+ def __cinit__(self):
+ """This class is *not* meant to be initialized directly, but instead
+ through subclasses. Those subclasses need to implement at a minimum
+ the setting of itemsize, but can optionally also implement setup_objs
+ and teardown_objs to either set default values or initialize additional
+ pointers and values, and then free them."""
+ self.containers = NULL
+ self.n_con = 0
+ self.itemsize = -1 # Never use the base class
+
+ def __dealloc__(self):
+ cdef int i
+ cdef AllocationContainer *obj
+ for i in range(self.n_con):
+ obj = &self.containers[i]
+ self.teardown_objs(obj.my_objs, obj.n, obj.offset, obj.con_id)
+ if self.containers != NULL:
+ free(self.containers)
+
+ def __getitem__(self, int i):
+ """This returns an array view (if possible and implemented in a
+ subclass) on the pool of objects specified by i."""
+ return self._con_to_array(i)
+
+ def __len__(self):
+ return self.n_con
+
+ def append(self, int n_objs, np.int64_t con_id = -1):
+ """This allocates a new batch of n_objs objects, with the container id
+ specified as con_id. Return value is a view on them."""
+ self.allocate_objs(n_objs, con_id)
+ return self[self.n_con - 1]
+
+ cdef void allocate_objs(self, int n_objs, np.int64_t con_id = -1) except *:
+ cdef AllocationContainer *n_cont, *prev
+ cdef int n, i, j, k
+ cdef char *obj # char so we can do pointer math
+ self.containers = <AllocationContainer*> realloc(
+ self.containers,
+ sizeof(AllocationContainer) * (self.n_con + 1))
+ n_cont = &self.containers[self.n_con]
+ if self.n_con == 0:
+ n_cont.offset = 0
+ else:
+ prev = &self.containers[self.n_con - 1]
+ n_cont.offset = prev.offset + prev.n
+ self.n_con += 1
+ n_cont.my_objs = malloc(self.itemsize * n_objs)
+ if n_cont.my_objs == NULL:
+ raise MemoryError
+ n_cont.n = n_objs
+ n_cont.n_assigned = 0
+ n_cont.con_id = con_id
+ obj = <char*> n_cont.my_objs
+ self.setup_objs(n_cont.my_objs, n_objs, n_cont.offset, n_cont.con_id)
+
+ cdef void setup_objs(self, void *obj, np.uint64_t count,
+ np.uint64_t offset, np.int64_t con_id):
+ """This can be overridden in the subclass, where it can initialize any
+ of the allocated objects."""
+ pass
+
+ cdef void teardown_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
+ np.int64_t con_id):
+ # We assume that these are all allocated and have no sub-allocations
+ """If overridden, additional behavior can be provided during teardown
+ of allocations. For instance, if you allocate some memory on each of
+ the allocated objects."""
+ if obj != NULL:
+ free(obj)
+
+ def to_arrays(self):
+ rv = []
+ cdef int i
+ for i in range(self.n_con):
+ rv.append(self._con_to_array(i))
+ return rv
+
+ def _con_to_array(self, int i):
+ """This has to be implemented in a subclass, and should return an
+ appropriate np.asarray() of a memoryview of self.my_objs."""
+ raise NotImplementedError
+
+cdef class BitmaskPool(ObjectPool):
+ def __cinit__(self):
+ """This is an example implementation of object pools for bitmasks
+ (uint8) arrays. It lets you reasonably quickly allocate a set of
+ uint8 arrays which can be accessed and modified, and then virtually
+ append to that."""
+ # Base class will ALSO be called
+ self.itemsize = sizeof(np.uint8_t)
+
+ cdef void setup_objs(self, void *obj, np.uint64_t n, np.uint64_t offset,
+ np.int64_t con_id):
+ cdef np.uint64_t i
+ cdef np.uint8_t *mask = <np.uint8_t *> obj
+ for i in range(n):
+ mask[i] = 0
+
+ def _con_to_array(self, int i):
+ cdef AllocationContainer *obj = &self.containers[i]
+ cdef np.uint8_t[:] o = <np.uint8_t[:obj.n]> (<np.uint8_t*> obj.my_objs)
+ rv = np.asarray(o)
+ return rv
diff -r c5bdb1f946cd9a9233b36a13a758840522b78914 -r 68cdeca5910d377f023631ecf6dbcae1d0794dc3 yt/utilities/lib/tests/test_allocation_container.py
--- /dev/null
+++ b/yt/utilities/lib/tests/test_allocation_container.py
@@ -0,0 +1,22 @@
+from yt.testing import \
+ assert_array_equal, assert_equal
+from yt.utilities.lib.allocation_container import \
+ BitmaskPool
+
+def test_bitmask_pool():
+ bmp = BitmaskPool()
+ assert_equal(len(bmp), 0)
+ bmp.append(100)
+ assert_equal(len(bmp), 1)
+ assert_equal(bmp[0].size, 100)
+ bmp.append(200)
+ assert_equal(len(bmp), 2)
+ assert_equal(bmp[0].size, 100)
+ assert_equal(bmp[1].size, 200)
+ assert_equal(sum(_.size for _ in bmp.to_arrays()), 300)
+ arrs = bmp.to_arrays()
+ assert_equal(arrs[0].size, 100)
+ assert_equal(arrs[1].size, 200)
+ arrs[0][:] = 1
+ arrs = bmp.to_arrays()
+ assert_array_equal(arrs[0], 1)
Repository URL: https://bitbucket.org/yt_analysis/yt/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the yt-svn
mailing list