Prev Next omp_alloc.cpp

@(@\newcommand{\W}[1]{ \; #1 \; } \newcommand{\R}[1]{ {\rm #1} } \newcommand{\B}[1]{ {\bf #1} } \newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} } \newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} } \newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} } \newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }@)@
OpenMP Memory Allocator: Example and Test

Deprecated 2011-08-31
This example is only intended to help convert calls to omp_alloc to calls to thread_alloc .
# include <cppad/utility/omp_alloc.hpp>
# include <cppad/utility/memory_leak.hpp>
# include <vector>

namespace { // Begin empty namespace

bool omp_alloc_bytes(void)
{     bool ok = true;
     using CppAD::omp_alloc;
     size_t thread;

     // check initial memory values
     ok &= ! CppAD::memory_leak();

     // amount of static memory used by thread zero
     size_t static_inuse = omp_alloc::inuse(0);

     // determine the currently executing thread
     // (should be zero because not in parallel mode)
     thread = omp_alloc::get_thread_num();

     // repeatedly allocate enough memory for at least two size_t values.
     size_t min_size_t = 2;
     size_t min_bytes  = min_size_t * sizeof(size_t);
     size_t n_outter   = 10;
     size_t n_inner    = 5;
     size_t cap_bytes(0), i, j, k;
     for(i = 0; i < n_outter; i++)
     {     // Do not use CppAD::vector here because its use of omp_alloc
          // complicates the inuse and avaialble results.
          std::vector<void*> v_ptr(n_inner);
          for( j = 0; j < n_inner; j++)
          {     // allocate enough memory for min_size_t size_t objects
               v_ptr[j]    = omp_alloc::get_memory(min_bytes, cap_bytes);
               size_t* ptr = reinterpret_cast<size_t*>(v_ptr[j]);
               // determine the number of size_t values we have obtained
               size_t  cap_size_t = cap_bytes / sizeof(size_t);
               ok                &= min_size_t <= cap_size_t;
               // use placement new to call the size_t copy constructor
               for(k = 0; k < cap_size_t; k++)
                    new(ptr + k) size_t(i + j + k);
               // check that the constructor worked
               for(k = 0; k < cap_size_t; k++)
                    ok &= ptr[k] == (i + j + k);
          }
          // check that n_inner * cap_bytes are inuse and none are available
          ok &= omp_alloc::inuse(thread) == n_inner*cap_bytes + static_inuse;
          ok &= omp_alloc::available(thread) == 0;
          // return the memrory to omp_alloc
          for(j = 0; j < n_inner; j++)
               omp_alloc::return_memory(v_ptr[j]);
          // check that now n_inner * cap_bytes are now available
          // and none are in use
          ok &= omp_alloc::inuse(thread) == static_inuse;
          ok &= omp_alloc::available(thread) == n_inner * cap_bytes;
     }
     // return all the available memory to the system
     omp_alloc::free_available(thread);
     ok &= ! CppAD::memory_leak();

     return ok;
}

class my_char {
public:
     char ch_ ;
     my_char(void) : ch_(' ')
     { }
     my_char(const my_char& my_ch) : ch_(my_ch.ch_)
     { }
};

bool omp_alloc_array(void)
{     bool ok = true;
     using CppAD::omp_alloc;
     size_t i;

     // check initial memory values
     size_t thread = omp_alloc::get_thread_num();
     ok &= thread == 0;
     ok &= ! CppAD::memory_leak();
     size_t static_inuse = omp_alloc::inuse(0);

     // initial allocation of an array
     size_t  size_min  = 3;
     size_t  size_one;
     my_char *array_one  =
          omp_alloc::create_array<my_char>(size_min, size_one);

     // check the values and change them to null 'x'
     for(i = 0; i < size_one; i++)
     {     ok &= array_one[i].ch_ == ' ';
          array_one[i].ch_ = 'x';
     }

     // now create a longer array
     size_t size_two;
     my_char *array_two =
          omp_alloc::create_array<my_char>(2 * size_min, size_two);

     // check the values in array one
     for(i = 0; i < size_one; i++)
          ok &= array_one[i].ch_ == 'x';

     // check the values in array two
     for(i = 0; i < size_two; i++)
          ok &= array_two[i].ch_ == ' ';

     // check the amount of inuse and available memory
     // (an extra size_t value is used for each memory block).
     size_t check = static_inuse + sizeof(my_char)*(size_one + size_two);
     ok   &= omp_alloc::inuse(thread) - check < sizeof(my_char);
     ok   &= omp_alloc::available(thread) == 0;

     // delete the arrays
     omp_alloc::delete_array(array_one);
     omp_alloc::delete_array(array_two);
     ok   &= omp_alloc::inuse(thread) == static_inuse;
     check = sizeof(my_char)*(size_one + size_two);
     ok   &= omp_alloc::available(thread) - check < sizeof(my_char);

     // free the memory for use by this thread
     omp_alloc::free_available(thread);
     ok &= ! CppAD::memory_leak();

     return ok;
}
} // End empty namespace

bool omp_alloc(void)
{     bool ok  = true;
     using CppAD::omp_alloc;

     // check initial state of allocator
     ok  &= omp_alloc::get_max_num_threads() == 1;

     // set the maximum number of threads greater than one
     // so that omp_alloc holds onto memory
     CppAD::omp_alloc::set_max_num_threads(2);
     ok  &= omp_alloc::get_max_num_threads() == 2;
     ok  &= ! CppAD::memory_leak();

     // now use memory allocator in state where it holds onto memory
     ok   &= omp_alloc_bytes();
     ok   &= omp_alloc_array();

     // check that the tests have not held onto memory
     ok  &= ! CppAD::memory_leak();

     // set the maximum number of threads back to one
     // so that omp_alloc no longer holds onto memory
     CppAD::omp_alloc::set_max_num_threads(1);

     return ok;
}


Input File: example/deprecated/omp_alloc.cpp