{ "metadata": { "name": "", "signature": "sha256:1c0c2f07e0bd340a99e757d3bb8384bdb42810679830dcd3f2dafb331a8a1c5d" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Memory Manager\n", "==============\n", "\n", "Oftentimes it is necessary to use scratch Image3D's and Field3D's. However, the continual allocation and deallocation of large chunks of memory can be time consuming. Therefore, we make this process more efficient by using the PyCA Memory Manager. Instead of initializing Image3D's and Field3D's, we use the equivalent ManagedImage3D's and ManagedField3D's. The only difference is that when a Managed Image/Field's memory is allocated, it is allocated using memory stored in the MemoryManager, and when a Image/Field is destructed, it's memory is returned to the memory manager.\n", "\n", "The memory manager is initialized with a grid and will allocate N pools of memory with the grid size." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import PyCA.Core as ca\n", "grid = ca.GridInfo(ca.Vec3Di(64, 64, 32))\n", "mType = ca.MEM_DEVICE\n", "# Initialize memory manager by allocating 4 64x64x32 pools of memory on the GPU\n", "ca.ThreadMemoryManager.init(grid, mType, 4)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "markdown", "metadata": {}, "source": [ "To use the memory manager, we create a ManagedImage3D (using 1 pool of memory) or ManagedField3D (using 3 pools of memory). If we go over our initially allotted number of memory pools, the memory manager will automatically increase its number of pools. However, it will never decrease it's size (which would defeat the purpose). For Example:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "TempIm1 = ca.ManagedImage3D(grid, mType) #using 1/4 pools\n", "TempIm2 = ca.ManagedImage3D(grid, mType) #using 2/4 pools\n", "TempVF1 = ca.ManagedField3D(grid, mType) #using 5/5 pools\n", "TempVF2 = ca.ManagedField3D(grid, mType) #using 8/8 pools\n", "del(TempIm1) #using 7/8 pools\n", "TempVF3 = ca.ManagedField3D(grid, mType) #using 10/10 pools\n", "del(TempVF1) #using 7/10 pools\n", "TempIm3 = ca.ManagedImage3D(grid, mType) #using 8/10 pools" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 2 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The thread memory manager is globally defined and doesn't need to be passed into functions. We can see the max number of pools by declaring a local instance of the memory manger and using the `getNumPools` method." ] }, { "cell_type": "code", "collapsed": false, "input": [ "global_mm = ca.ThreadMemoryManager.instance()\n", "print 'Total number of mem pools:', global_mm.getNumPools()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Total number of mem pools: 10\n" ] } ], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Non-standard Grids\n", "\n", "When creating ManagedImage3D's and ManagedField3D's, we are not required to use identical grids as the grid defined by the memory manager. In fact, our spacing and origin have no effect, as they have no effect on the memory requirements. However, our grids _may not_ be larger than the grid of the initialized memory manager." ] }, { "cell_type": "code", "collapsed": false, "input": [ "grid1 = ca.GridInfo(ca.Vec3Di(32,64,64)) #Allowed\n", "grid2 = ca.GridInfo(ca.Vec3Di(100,100,1)) #Allowed\n", "grid3 = ca.GridInfo(ca.Vec3Di(1, 1, 1)) #Allowed\n", "grid4 = ca.GridInfo(ca.Vec3Di(64, 64, 64)) #Not Allowed\n", "\n", "TempIm1 = ca.ManagedImage3D(grid1, mType)\n", "TempIm2 = ca.ManagedImage3D(grid2, mType)\n", "TempIm3 = ca.ManagedImage3D(grid3, mType)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 4 }, { "cell_type": "code", "collapsed": false, "input": [ "TempIm4 = ca.ManagedImage3D(grid4, mType) #Will throw an Exception" ], "language": "python", "metadata": {}, "outputs": [ { "ename": "RuntimeError", "evalue": "PyCA::ManagedImage3D::ManagedImage3D(PyCA::GridInfo const &,PyCA::MemoryType):\nPyCAException : From /local/crottman/git/PyCA/Code/Cxx/src/base/MemoryManager.cxx:137 : Grid too large", "output_type": "pyerr", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mRuntimeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mTempIm4\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mca\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mManagedImage3D\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mgrid4\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmType\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32m/local/crottman/software/pyca-bin/python_module/PyCA/Core.pyc\u001b[0m in \u001b[0;36m__init__\u001b[1;34m(self, *args)\u001b[0m\n\u001b[0;32m 2268\u001b[0m \u001b[0m__init__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mPyCA\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mManagedImage3D\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mGridInfo\u001b[0m \u001b[0mgrid\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mPyCA\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mMemoryType\u001b[0m \u001b[0mmType\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mMemoryManager\u001b[0m \u001b[0mmm\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m-\u001b[0m\u001b[1;33m>\u001b[0m \u001b[0mManagedImage3D\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2269\u001b[0m \"\"\"\n\u001b[1;32m-> 2270\u001b[1;33m \u001b[0mthis\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0m_Core\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnew_ManagedImage3D\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2271\u001b[0m \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mthis\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mthis\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2272\u001b[0m \u001b[1;32mexcept\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mthis\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mthis\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mRuntimeError\u001b[0m: PyCA::ManagedImage3D::ManagedImage3D(PyCA::GridInfo const &,PyCA::MemoryType):\nPyCAException : From /local/crottman/git/PyCA/Code/Cxx/src/base/MemoryManager.cxx:137 : Grid too large" ] } ], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Although you can create ManagedImage3D's and ManagedField3D's with grids smaller than the memroy manager's grid, it may not be wise to do so especially if the new grid size is significantly smaller than the memory manager's grid size. For example, if you initialized the memory manager with a 256x256x256 sized grid and created 10 ManagedImage3D's with a 1x1x1 sized grid, you would be allocating much more memory than necessary (since the memory manager would allocate 10 256x256x256 memory pools)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Multiple Memory Managers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You are only allowed to initialize one global thread memory manager. However, if you have multiple grids that you need managed, you can create additional memory managers. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "newgrid = ca.GridInfo(ca.Vec3Di(50, 50, 1))\n", "mType = ca.MEM_DEVICE\n", "mem_man_2 = ca.MemoryManager(grid, mType, 1)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 6 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The main difference in using this memory manager to create a ManagedImage3D or a ManagedField3D is that you need to include the specific memory manger in the Image/Field's initialization. If this is not specified, it will create a Managed Image/Field from the thread memory manager." ] }, { "cell_type": "code", "collapsed": false, "input": [ "TempIm = ca.ManagedImage3D(newgrid, mType, mem_man_2)\n", "TempVF = ca.ManagedField3D(newgrid, mType, mem_man_2)\n", "print 'Total number of mem pools:', mem_man_2.getNumPools()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Total number of mem pools: 4\n" ] } ], "prompt_number": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Deleting Memory Managers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Local memory managers will be deleted by Python's garbage collector. If you want to delete the thread memory manager, you can delete it by calling the destructor. When you do this, a message will print out to the terminal telling you the maximum temporary pools were used." ] }, { "cell_type": "code", "collapsed": false, "input": [ "del(mem_man_2) #delete the local memory manager\n", "ca.ThreadMemoryManager.destroy() #delete the thread memory manager" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 8 } ], "metadata": {} } ] }