aboutsummaryrefslogtreecommitdiff
path: root/pkg/proto/vol/src/pv_gmem.x
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /pkg/proto/vol/src/pv_gmem.x
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'pkg/proto/vol/src/pv_gmem.x')
-rw-r--r--pkg/proto/vol/src/pv_gmem.x109
1 files changed, 109 insertions, 0 deletions
diff --git a/pkg/proto/vol/src/pv_gmem.x b/pkg/proto/vol/src/pv_gmem.x
new file mode 100644
index 00000000..646baf47
--- /dev/null
+++ b/pkg/proto/vol/src/pv_gmem.x
@@ -0,0 +1,109 @@
+include <imhdr.h>
+
+# PV_GMEM -- Determine how much memory we can get and actually use for the
+# volume rotation sequence. We only allocate actual memory temporarily in
+# order to see how much is really available; IMIO will later take care of
+# the actual io buffer allocation.
+
+define DECR_MEM 0.8 # decrement mem by magic factor
+
+
+procedure pv_gmem (im1, im2, use_both, verbose, max_ws, len_x, oldsize)
+pointer im1 # Input 3d image.
+pointer im2 # Output projected image(s)
+bool use_both # Use both opacity and intensity voxels
+int verbose # Report memory usage?
+int max_ws # Maximum working set to allocate
+int len_x # (output) safe amount of memory to use
+int oldsize # (output) old memory to be reset at termination
+
+int intype, outtype, reqmem, gotmem, needmem, maxsize
+int yzslice_pix, yzreq
+pointer buf_in
+bool topped_out
+
+int begmem(), sizeof()
+errchk begmem(), malloc()
+
+begin
+ # See how much memory we can get; if we cannot get whole input image
+ # into memory, do it in chunks of yz slices.
+ intype = IM_PIXTYPE(im1)
+ outtype = IM_PIXTYPE(im2)
+ reqmem = IM_LEN(im1,1) * IM_LEN(im1,2) * IM_LEN(im1,3)
+ reqmem = reqmem * sizeof (intype)
+ if (use_both)
+ reqmem = 2 * reqmem
+
+ # Add output buffer.
+ reqmem = reqmem + IM_LEN(im2,1) * sizeof (outtype)
+
+ # Decrease to max_ws (a task parameter in CHAR units).
+ reqmem = min (reqmem, max_ws)
+
+ repeat {
+ iferr (gotmem = begmem (reqmem, oldsize, maxsize)) {
+ reqmem = reqmem * DECR_MEM
+ if (verbose == YES) {
+ call eprintf ("ERR gotmem=begmem(); retrying at size %d\n")
+ call pargi (reqmem)
+ }
+ } else {
+ if (verbose == YES) {
+ call eprintf ("gotmem=%d, oldsize=%d, maxsize=%d\n")
+ call pargi (gotmem)
+ call pargi (oldsize)
+ call pargi (maxsize)
+ }
+ break
+ }
+ }
+
+ # Make sure it is really available, and if not, decrement to largest
+ # number of yz slices possible.
+ needmem = gotmem
+ yzslice_pix = IM_LEN(im1,2) * IM_LEN(im1,3)
+ yzreq = yzslice_pix * sizeof(intype)
+ if (yzreq - IM_LEN(im1,1) * sizeof(TY_REAL) > needmem) {
+ call eprintf ("Not enough memory for 1 yz slice of input image\n")
+ call error (0, "Out of memory")
+ }
+ topped_out = false
+ repeat {
+ iferr (call malloc (buf_in, needmem, intype)) {
+ needmem = needmem - yzreq
+ if (needmem < yzreq) {
+ call eprintf ("Had to decrease memory too much")
+ call error (0, "Memory allocation error (yzslice_pix)")
+ }
+ topped_out = true
+ } else {
+ call mfree (buf_in, intype)
+ break
+ }
+ }
+
+ # Experiments show that horrible things happen if we actually use
+ # this much memory. Decrease by magic factor.
+ if (topped_out) {
+ call fixmem (max (needmem, oldsize))
+ if (verbose == YES) {
+ call eprintf ("Had to decrease memory for malloc().")
+ call eprintf (" Working set now %d\n")
+ call pargi (needmem)
+ }
+ needmem = needmem * DECR_MEM
+ if (verbose == YES) {
+ call eprintf ("Remaining memory for image buffers = %d\n")
+ call pargi (needmem)
+ }
+ }
+ if (needmem < yzreq) {
+ call eprintf ("Not enough memory for 1 yz slice of input image\n")
+ call error (0, "Out of memory")
+ }
+
+ # We return the number of columns to gulp from the input image at one
+ # time and oldmem so the task can release its memory on completion.
+ len_x = needmem / yzreq
+end