Actions

icon Post
text/html Subscribe
text/html Unsubscribe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vsipl++] [patch] Pool allocation


  • To: VSIPL++ Developers List <vsipl++@xxxxxxxxxxxxxxxx>
  • Subject: [vsipl++] [patch] Pool allocation
  • From: Jules Bergmann <jules@xxxxxxxxxxxxxxxx>
  • Date: Wed, 30 Jan 2008 16:15:40 -0500

Now that 1.4 has been branched ...

This allows memory for blocks to be allocated from special pools. The default pool allocates aligned memory (using alloc_align) similar to the status quo. By using a different pool allocator, memory can be allocated from special pools, such as from a pool of huge page memory, or from a pool of special DMA memory, etc.

Dense blocks determine their pool from their map, effectively from Local_map.

Currently controlling the pool is a bit of hack. When a Local_map is constructed, it captures the current default pool. This allows you to write code like:

	... set pool to X
	
	// create views using pool X
	Vector<...> view(...)

	... set pool to something else

In the future, we could add more elegant ways to set the pool associated with a Local map

	Local_map loc_aligned(... aligned pool ...);
	Local_map loc_huge(... use huge pool...)

	Vector<float> small(4, loc_aligned);
	Vector<float> big(16384, loc_huge);

An immediate impact of this patch is that it allows us to use huge pages with all of then benchmarks, instead of rewriting them to explicitly allocate/use huge pages.

Thought?  Ok to apply?

				-- Jules


--
Jules Bergmann
CodeSourcery
jules@xxxxxxxxxxxxxxxx
(650) 331-3385 x705
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 192285)
+++ ChangeLog	(working copy)
@@ -1,5 +1,23 @@
 2008-01-30  Jules Bergmann  <jules@xxxxxxxxxxxxxxxx>
 
+	* src/vsip/initfin.cpp: Initialize default pool.
+	* src/vsip/dense.hpp: Use pools for allocation.
+	* src/vsip/core/pool.hpp: New file, pool virtual base class header.
+	* src/vsip/core/pool.cpp: New file, pool virtual base class impl.
+	* src/vsip/core/huge_page_pool.hpp: New file, pool implementation
+	  using huge page memory header.
+	* src/vsip/core/huge_page_pool.cpp:  New file, pool implementation
+	  using huge page memory impl.
+	* src/vsip/core/aligned_pool.hpp: New file, pool implementation 
+	  using alloc_align header.
+	* src/vsip/core/aligned_pool.cpp: New file, pool implementation 
+	  using alloc_align impl.
+	* src/vsip/core/parallel/local_map.hpp: Hold pool.
+	* benchmarks/loop.hpp: Allow alternate pool to be used.
+	* benchmarks/main.cpp: Likewise.
+
+2008-01-30  Jules Bergmann  <jules@xxxxxxxxxxxxxxxx>
+
 	* m4/lapack.m4: Detect ATLAS with v3 lapack/blas, as found on
 	  Ubuntu 7.04.
 
Index: src/vsip/initfin.cpp
===================================================================
--- src/vsip/initfin.cpp	(revision 191870)
+++ src/vsip/initfin.cpp	(working copy)
@@ -13,6 +13,7 @@
 #include <vsip/initfin.hpp>
 #include <vsip/vector.hpp>
 #include <vsip/core/parallel/services.hpp>
+#include <vsip/core/pool.hpp>
 #if defined(VSIP_IMPL_CBE_SDK) && !defined(VSIP_IMPL_REF_IMPL)
 # include <vsip/opt/cbe/ppu/task_manager.hpp>
 #endif
@@ -210,6 +211,8 @@
 
   par_service_ = new impl::Par_service(use_argc, use_argv);
 
+  impl::initialize_default_pool(use_argc, use_argv);
+
   // Copy argv back if necessary
   if (argv_is_tmp)
   {
Index: src/vsip/dense.hpp
===================================================================
--- src/vsip/dense.hpp	(revision 191870)
+++ src/vsip/dense.hpp	(working copy)
@@ -26,6 +26,7 @@
 #include <vsip/core/block_traits.hpp>
 #include <vsip/core/parallel/choose_dist_block.hpp>
 #include <vsip/domain.hpp>
+#include <vsip/core/pool.hpp>
 
 /// Complex storage format for dense blocks.
 #if VSIP_IMPL_PREFER_SPLIT_COMPLEX
@@ -295,8 +296,7 @@
 
 
 template <typename ComplexFmt,
-	  typename T,
-	  typename AllocT = vsip::impl::Aligned_allocator<T> >
+	  typename T>
 class Dense_storage
 {
   // Compile-time values and types.
@@ -306,23 +306,21 @@
 
   // Constructors and destructor.
 public:
-  Dense_storage(length_type   size,
-		type          buffer = NULL,
-		AllocT const& allocator = AllocT())
+  Dense_storage(Pool*         pool,
+		length_type   size,
+		type          buffer = NULL)
     VSIP_THROW((std::bad_alloc))
-    : allocator_ (allocator),
-      alloc_data_(buffer == NULL),
-      data_      (alloc_data_ ? allocator_.allocate(size) : (T*)buffer)
+    : alloc_data_(buffer == NULL),
+      data_      (alloc_data_ ? pool_alloc<T>(pool, size) : (T*)buffer)
   {}
 
-  Dense_storage(length_type   size,
+  Dense_storage(Pool*         pool,
+		length_type   size,
 		T             val,
-		type          buffer = NULL,
-		AllocT const& allocator = AllocT())
+		type          buffer = NULL)
   VSIP_THROW((std::bad_alloc))
-    : allocator_ (allocator),
-      alloc_data_(buffer == NULL),
-      data_      (alloc_data_ ? allocator_.allocate(size) : (T*)buffer)
+    : alloc_data_(buffer == NULL),
+      data_      (alloc_data_ ? pool_alloc<T>(pool, size) : (T*)buffer)
   {
     for (index_type i=0; i<size; ++i)
       data_[i] = val;
@@ -337,13 +335,13 @@
 
   // Accessors.
 protected:
-  void impl_rebind(length_type size, type buffer);
+  void impl_rebind(Pool* pool, length_type size, type buffer);
 
-  void deallocate(length_type size)
+  void deallocate(Pool* pool, length_type size)
   {
     if (alloc_data_)
     {
-      allocator_.deallocate(data_, size);
+      pool_dealloc(pool, data_, size);
       data_ = 0;
     }
   }
@@ -363,16 +361,14 @@
 
   // Member data.
 private:
-  AllocT allocator_;
   bool   alloc_data_;
   T*     data_;
 };
 
 
 
-template <typename T,
-	  typename AllocT>
-class Dense_storage<Cmplx_split_fmt, vsip::complex<T>, AllocT>
+template <typename T>
+class Dense_storage<Cmplx_split_fmt, vsip::complex<T> >
 {
   // Compile-time values and types.
 public:
@@ -381,23 +377,23 @@
 
   // Constructors and destructor.
 public:
-  Dense_storage(length_type   size,
-		type          buffer    = type(0, 0),
-		AllocT const& allocator = AllocT())
+  Dense_storage(Pool*         pool,
+		length_type   size,
+		type          buffer    = type(0, 0))
     VSIP_THROW((std::bad_alloc))
-    : allocator_ (allocator),
-      alloc_data_(buffer.first == NULL || buffer.second == NULL),
-      real_data_ (alloc_data_ ? allocator_.allocate(size) : buffer.first),
-      imag_data_ (alloc_data_ ? allocator_.allocate(size) : buffer.second)
+    : alloc_data_(buffer.first == NULL || buffer.second == NULL),
+      real_data_ (alloc_data_ ? pool_alloc<T>(pool, size) : buffer.first),
+      imag_data_ (alloc_data_ ? pool_alloc<T>(pool, size) : buffer.second)
   {}
 
-  Dense_storage(length_type      size,
+  Dense_storage(Pool*            pool,
+		length_type      size,
 		vsip::complex<T> val,
 		type buffer = type(0, 0))
     VSIP_THROW((std::bad_alloc))
     : alloc_data_(buffer.first == NULL || buffer.second == NULL),
-      real_data_ (alloc_data_ ? allocator_.allocate(size) : buffer.first),
-      imag_data_ (alloc_data_ ? allocator_.allocate(size) : buffer.second)
+      real_data_ (alloc_data_ ? pool_alloc<T>(pool, size) : buffer.first),
+      imag_data_ (alloc_data_ ? pool_alloc<T>(pool, size) : buffer.second)
   {
     for (index_type i=0; i<size; ++i)
       real_data_[i] = val.real();
@@ -414,14 +410,14 @@
 
   // Accessors.
 protected:
-  void impl_rebind(length_type size, type buffer);
+  void impl_rebind(Pool* pool, length_type size, type buffer);
 
-  void deallocate(length_type size)
+  void deallocate(Pool* pool, length_type size)
   {
     if (alloc_data_)
     {
-      allocator_.deallocate(real_data_, size);
-      allocator_.deallocate(imag_data_, size);
+      pool_dealloc(pool, real_data_, size);
+      pool_dealloc(pool, imag_data_, size);
       real_data_ = 0;
       imag_data_ = 0;
     }
@@ -452,7 +448,6 @@
 
   // Member data.
 private:
-  typename AllocT::template rebind<T>::other allocator_;
   bool   alloc_data_;
   T*     real_data_;
   T*     imag_data_;
@@ -525,7 +520,7 @@
     VSIP_THROW((std::bad_alloc));
 
   ~Dense_impl() VSIP_NOTHROW
-    { storage_type::deallocate(layout_.total_size()); }
+    { storage_type::deallocate(map_.impl_pool(), layout_.total_size()); }
 
 public:
   using storage_type::get;
@@ -1273,17 +1268,17 @@
 ///   SIZE to be size object was constructed with.
 
 template <typename ComplexFmt,
-	  typename T,
-	  typename AllocT>
+	  typename T>
 void
-Dense_storage<ComplexFmt, T, AllocT>::impl_rebind(
+Dense_storage<ComplexFmt, T>::impl_rebind(
+  Pool*       pool,
   length_type size,
   type        buffer)
 {
   if (buffer != NULL)
   {
     if (alloc_data_)
-      allocator_.deallocate(data_, size);
+      pool_dealloc<T>(pool, data_, size);
     
     alloc_data_ = false;
     data_       = buffer;
@@ -1293,7 +1288,7 @@
     if (!alloc_data_)
     {
       alloc_data_ = true;
-      data_ = allocator_.allocate(size);
+      data_ = pool_alloc<T>(pool, size);
     }
     /* else do nothing - we already own our data */
   }
@@ -1306,10 +1301,10 @@
 /// Requires:
 ///   SIZE to be size object was constructed with.
 
-template <typename T,
-	  typename AllocT>
+template <typename T>
 void
-Dense_storage<Cmplx_split_fmt, vsip::complex<T>, AllocT>::impl_rebind(
+Dense_storage<Cmplx_split_fmt, vsip::complex<T> >::impl_rebind(
+  Pool*       pool,
   length_type size,
   type        buffer)
 {
@@ -1317,8 +1312,8 @@
   {
     if (alloc_data_)
     {
-      allocator_.deallocate(real_data_, size);
-      allocator_.deallocate(imag_data_, size);
+      pool_dealloc(pool, real_data_, size);
+      pool_dealloc(pool, imag_data_, size);
     }
     
     alloc_data_ = false;
@@ -1330,8 +1325,8 @@
     if (!alloc_data_)
     {
       alloc_data_ = true;
-      real_data_ = allocator_.allocate(size);
-      imag_data_ = allocator_.allocate(size);
+      real_data_ = pool_alloc<T>(pool, size);
+      imag_data_ = pool_alloc<T>(pool, size);
     }
     /* else do nothing - we already own our data */
   }
@@ -1353,7 +1348,7 @@
   Domain<Dim> const& dom,
   MapT const&        map)
 VSIP_THROW((std::bad_alloc))
-  : storage_type(applied_layout_type(dom).total_size()),
+  : storage_type(map.impl_pool(), applied_layout_type(dom).total_size()),
     layout_     (dom),
     map_        (map),
     admitted_   (true)
@@ -1374,7 +1369,7 @@
   T                  val,
   MapT const&        map)
 VSIP_THROW((std::bad_alloc))
-  : storage_type(applied_layout_type(dom).total_size(), val),
+  : storage_type(map.impl_pool(), applied_layout_type(dom).total_size(), val),
     layout_     (dom),
     map_        (map),
     admitted_   (true)
@@ -1410,7 +1405,7 @@
   User_storage<T> const& user_data,
   MapT const&            map)
 VSIP_THROW((std::bad_alloc))
-  : storage_type(applied_layout_type(dom).total_size(),
+  : storage_type(map.impl_pool(), applied_layout_type(dom).total_size(),
 		 user_data.as_storage(complex_type())),
     layout_     (dom),
     user_data_  (user_data),
@@ -1747,8 +1742,9 @@
 {
   assert(!this->admitted() && this->user_storage() == array_format);
   this->user_data_.rebind(pointer);
-  this->impl_rebind(layout_.total_size(),
-	       this->user_data_.as_storage(complex_type()));
+  this->impl_rebind(
+		map_.impl_poo(), layout_.total_size(),
+		this->user_data_.as_storage(complex_type()));
 }
 
 
@@ -1776,8 +1772,8 @@
 	 (this->user_storage() == split_format ||
 	  this->user_storage() == interleaved_format));
   this->user_data_.rebind(pointer);
-  this->impl_rebind(layout_.total_size(),
-			this->user_data_.as_storage(complex_type()));
+  this->impl_rebind(map_.impl_pool(), layout_.total_size(),
+		    this->user_data_.as_storage(complex_type()));
 }
 
 
@@ -1807,8 +1803,9 @@
 	 (this->user_storage() == split_format ||
 	  this->user_storage() == interleaved_format));
   this->user_data_.rebind(real_pointer, imag_pointer);
-  this->impl_rebind(layout_.total_size(),
-			this->user_data_.as_storage(complex_type()));
+  this->impl_rebind(map_.impl_pool(),
+		    layout_.total_size(),
+		    this->user_data_.as_storage(complex_type()));
 }
 
 
Index: src/vsip/core/pool.hpp
===================================================================
--- src/vsip/core/pool.hpp	(revision 0)
+++ src/vsip/core/pool.hpp	(revision 0)
@@ -0,0 +1,81 @@
+/* Copyright (c) 2007 by CodeSourcery, LLC.  All rights reserved. */
+
+/** @file    vsip/core/pool.hpp
+    @author  Jules Bergmann
+    @date    2007-04-11
+    @brief   VSIPL++ Library: Memory allocation pool
+*/
+
+#ifndef VSIP_CORE_POOL_HPP
+#define VSIP_CORE_POOL_HPP
+
+/***********************************************************************
+  Included Files
+***********************************************************************/
+
+#include <limits>
+#include <cstdlib>
+#include <stdexcept>
+
+#include <vsip/support.hpp>
+
+
+
+/***********************************************************************
+  Declarations
+***********************************************************************/
+
+namespace vsip
+{
+
+namespace impl 
+{
+
+/// Pool base class.
+
+class Pool
+{
+public:
+  Pool() {}
+  virtual ~Pool();
+
+  virtual void* allocate(size_t size) = 0;
+  virtual void  deallocate(void* ptr, size_t size) = 0;
+
+  virtual char const* name() = 0;
+};
+
+
+extern Pool* default_pool;
+
+void initialize_default_pool(int& argc, char**&argv);
+
+
+
+template <typename T>
+inline T*
+pool_alloc(
+  Pool*       pool,
+  length_type size)
+{
+  return (T*)(pool->allocate(size * sizeof(T)));
+}
+
+
+
+template <typename T>
+inline void
+pool_dealloc(
+  Pool*       pool,
+  T*          ptr,
+  length_type size)
+{
+  pool->deallocate(ptr, size * sizeof(T));
+}
+
+
+} // namespace vsip::impl
+
+} // namespace vsip
+
+#endif // VSIP_CORE_POOL_HPP
Index: src/vsip/core/huge_page_pool.hpp
===================================================================
--- src/vsip/core/huge_page_pool.hpp	(revision 0)
+++ src/vsip/core/huge_page_pool.hpp	(revision 0)
@@ -0,0 +1,69 @@
+/* Copyright (c) 2007 by CodeSourcery, LLC.  All rights reserved. */
+
+/** @file    vsip/core/huge_page_pool.hpp
+    @author  Jules Bergmann
+    @date    2007-04-11
+    @brief   VSIPL++ Library: Memory allocation pool
+*/
+
+#ifndef VSIP_CORE_HUGE_PAGE_POOL_HPP
+#define VSIP_CORE_HUGE_PAGE_POOL_HPP
+
+/***********************************************************************
+  Included Files
+***********************************************************************/
+
+#include <limits>
+#include <cstdlib>
+
+#include <vsip/core/pool.hpp>
+
+
+
+/***********************************************************************
+  Declarations
+***********************************************************************/
+
+namespace vsip
+{
+
+namespace impl 
+{
+
+class Huge_page_pool : public Pool
+{
+public:
+  static size_t const align = 128;
+
+  // Constructors and destructor.
+public:
+  Huge_page_pool(const char* file, int pages);
+  ~Huge_page_pool();
+
+  // Pool accessors.
+public:
+  void* allocate(size_t size);
+  void  deallocate(void* ptr, size_t size);
+
+  char const* name();
+
+  // Impl accessors.
+public:
+  size_t total_avail() { return total_avail_; }
+
+  // Member data.
+private:
+  char*  pool_;
+  size_t size_;
+  char*  free_;
+
+  size_t total_avail_;
+};
+
+
+
+} // namespace vsip::impl
+
+} // namespace vsip
+
+#endif // VSIP_CORE_HUGE_PAGE_POOL_HPP
Index: src/vsip/core/aligned_pool.hpp
===================================================================
--- src/vsip/core/aligned_pool.hpp	(revision 0)
+++ src/vsip/core/aligned_pool.hpp	(revision 0)
@@ -0,0 +1,60 @@
+/* Copyright (c) 2007 by CodeSourcery, LLC.  All rights reserved. */
+
+/** @file    vsip/core/aligned_pool.hpp
+    @author  Jules Bergmann
+    @date    2007-04-12
+    @brief   VSIPL++ Library: Memory allocation pool
+*/
+
+#ifndef VSIP_CORE_ALIGNED_POOL_HPP
+#define VSIP_CORE_ALIGNED_POOL_HPP
+
+/***********************************************************************
+  Included Files
+***********************************************************************/
+
+#include <vsip/core/config.hpp>
+#include <vsip/core/pool.hpp>
+#include <vsip/core/allocation.hpp>
+#include <vsip/support.hpp>
+
+
+
+/***********************************************************************
+  Declarations
+***********************************************************************/
+
+namespace vsip
+{
+
+namespace impl 
+{
+
+/// Aligned_pool implementation.
+
+class Aligned_pool
+  : public Pool
+{
+public:
+  static size_t const align = VSIP_IMPL_ALLOC_ALIGNMENT;
+
+  // Constructors and destructor.
+public:
+  Aligned_pool();
+  ~Aligned_pool();
+
+  // Accessors.
+public:
+  void* allocate(size_t size);
+  void  deallocate(void* ptr, size_t size);
+
+  char const* name();
+};
+  
+  
+
+} // namespace vsip::impl
+
+} // namespace vsip
+
+#endif // VSIP_CORE_POOL_HPP
Index: src/vsip/core/pool.cpp
===================================================================
--- src/vsip/core/pool.cpp	(revision 0)
+++ src/vsip/core/pool.cpp	(revision 0)
@@ -0,0 +1,43 @@
+/* Copyright (c) 2007 by CodeSourcery, LLC.  All rights reserved. */
+
+/** @file    vsip/core/pool.cpp
+    @author  Jules Bergmann
+    @date    2007-04-11
+    @brief   VSIPL++ Library: Memory allocation pool
+*/
+
+/***********************************************************************
+  Included Files
+***********************************************************************/
+
+#include <limits>
+#include <cstdlib>
+
+#include <vsip/core/pool.hpp>
+#include <vsip/core/aligned_pool.hpp>
+
+
+
+/***********************************************************************
+  Declarations
+***********************************************************************/
+
+namespace vsip
+{
+
+namespace impl 
+{
+
+Pool::~Pool()
+{}
+
+Pool* default_pool = 0;
+
+void initialize_default_pool(int& /*argc*/, char**& /*argv*/)
+{
+  default_pool = new Aligned_pool();
+}
+
+} // namespace vsip::impl
+
+} // namespace vsip
Index: src/vsip/core/huge_page_pool.cpp
===================================================================
--- src/vsip/core/huge_page_pool.cpp	(revision 0)
+++ src/vsip/core/huge_page_pool.cpp	(revision 0)
@@ -0,0 +1,236 @@
+/* Copyright (c) 2007 by CodeSourcery, LLC.  All rights reserved. */
+
+/** @file    vsip/core/huge_page_pool.cpp
+    @author  Jules Bergmann
+    @date    2007-04-12
+    @brief   VSIPL++ Library: Memory allocation pool from huge pages
+*/
+
+/***********************************************************************
+  Included Files
+***********************************************************************/
+
+#include <limits>
+#include <cstdlib>
+#include <iostream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include <vsip/core/config.hpp>
+#include <vsip/core/allocation.hpp>
+#include <vsip/core/huge_page_pool.hpp>
+
+
+
+/***********************************************************************
+  Declarations
+***********************************************************************/
+
+namespace vsip
+{
+
+namespace impl 
+{
+
+// Allocate memory in huge page space (that are freed on program
+// termination)
+//
+// Requires
+//   MEM_FILE to be a filename in the /huge pages directory.
+//   PAGES to be the number of pages.
+//
+// Returns a pointer to the start of the memory if successful,
+//   NULL otherwise.
+
+char*
+open_huge_pages(char const* mem_file, int pages)
+{
+  int   fmem;
+  char* mem_addr;
+
+  if ((fmem = open(mem_file, O_CREAT | O_RDWR, 0755)) == -1)
+  {
+    std::cerr << "WARNING: unable to open file " << mem_file
+	      << " (errno=" << errno << " " << strerror(errno) << ")\n";
+    return 0;
+  }
+
+  // Delete file so that huge pages will get freed on program termination.
+  remove(mem_file);
+	
+  mem_addr = (char *)mmap(0, pages * 0x1000000,
+			   PROT_READ | PROT_WRITE, MAP_SHARED, fmem, 0);
+
+  if (mem_addr == MAP_FAILED)
+  {
+    std::cerr << "ERROR: unable to mmap file " << mem_file
+	      << " (errno=" << errno << " " << strerror(errno) << ")\n";
+    close(fmem);
+    return 0;
+  }
+
+    // Touch each of the large pages.
+    for (int i=0; i<pages; ++i)
+      mem_addr[i*0x1000000 + 0x0800000] = (char) 0;
+
+  return mem_addr;
+}
+
+
+
+/// Aligned_pool implementation.
+
+Huge_page_pool::Huge_page_pool(const char* file, int pages)
+  : pool_       (open_huge_pages(file, pages)),
+    size_       (pages * 0x1000000),
+    free_       (pool_),
+    total_avail_(size_)
+{
+  *(char**)free_ = 0; // next block
+  ((size_t*)free_)[1] = size_;
+}
+
+Huge_page_pool::~Huge_page_pool()
+{}
+
+void* 
+Huge_page_pool::allocate(size_t size)
+{
+  // std::cout << "allocate " << size << "\n";
+  // If size == 0, allocate 1 byte.
+  if (size < 2*sizeof(char*))
+    size = 2*sizeof(char*);
+
+  char*  prev  = 0;
+  char*  ptr   = free_;
+  size_t avail = ptr ? ((size_t*)ptr)[1] : 0;
+
+  while (ptr && avail < size)
+  {
+    // std::cout << " - skip " << avail << "\n";
+    prev  = ptr;
+    ptr   = *(char**)ptr;
+    avail = ptr ? ((size_t*)ptr)[1] : 0;
+  }
+
+  // std::cout << " = found " << avail << "\n";
+  if (ptr == 0)
+    VSIP_IMPL_THROW(std::bad_alloc());
+
+  total_avail_ -= size;
+
+  if (avail == size)
+  {
+    // std::cout << " - avail == size\n";
+    if (prev == 0)
+      free_ = *(char**)ptr;
+    else
+      *(char**)prev = *(char**)ptr;
+  }
+  else
+  {
+    if (prev == 0)
+    {
+      // std::cout << " - avail > size (moving free forward)\n";
+      free_ = ptr + size;
+    }
+    else
+    {
+      // std::cout << " - avail > size\n";
+      *(char**)prev = ptr + size;
+    }
+
+    *(char**)(ptr + size) = *(char**)ptr;
+    ((size_t*)(ptr + size))[1] = avail - size;
+  }
+
+  // std::cout << " = ptr: " << (void*)ptr << "\n";
+  return (void*)ptr;
+}
+
+void 
+Huge_page_pool::deallocate(void* return_ptr, size_t size)
+{
+  // std::cout << "deallocate " << size << " " << return_ptr << "\n";
+  if (size < 2*sizeof(char*))
+    size = 2*sizeof(char*);
+
+  char*  prev  = 0;
+  char*  ptr   = free_;
+
+  while (ptr && ptr < return_ptr)
+  {
+    prev  = ptr;
+    ptr   = *(char**)ptr;
+  }
+
+  if (ptr == 0)
+  {
+    // std::cout << " - free list empty\n";
+    ((size_t*)(return_ptr))[1] = size;
+    free_ = (char*)return_ptr;
+  }
+  else if (prev == 0)
+  {
+    assert(free_ == ptr);
+    assert(size <= ptr-(char*)return_ptr);
+    if (size == ptr - (char*)return_ptr)
+    {
+      // std::cout << " - insert at front of free list (merge)\n";
+      *(char**)(return_ptr)      = *(char**)ptr;
+      ((size_t*)(return_ptr))[1] = size + ((size_t*)(ptr))[1];
+      free_ = (char*)return_ptr;
+    }
+    else
+    {
+      // std::cout << " - insert at front of free list (no merge)\n";
+      *(char**)(return_ptr)      = ptr;
+      ((size_t*)(return_ptr))[1] = size;
+      free_ = (char*)return_ptr;
+    }
+  }
+  else
+  {
+    assert(size <= ptr-(char*)return_ptr);
+    if (size == ptr - (char*)return_ptr)
+    {
+      // std::cout << " - insert in middle of free list (merge)\n";
+      *(char**)(return_ptr)      = *(char**)ptr;
+      ((size_t*)(return_ptr))[1] = size + ((size_t*)(ptr))[1];
+    }
+    else
+    {
+      // std::cout << " - insert in middle of free list (no merge)\n";
+      *(char**)(return_ptr)      = ptr;
+      ((size_t*)(return_ptr))[1] = size;
+    }
+
+    size_t prev_size = ((size_t*)prev)[1];
+
+    if (prev_size == (char*)return_ptr - prev)
+    {
+      // std::cout << " + merge with prev\n";
+      *(char**)(prev) = *(char**)return_ptr;
+      ((size_t*)(prev))[1] = size + ((size_t*)(return_ptr))[1];
+    }
+    else
+      // std::cout << " + no merge with prev\n";
+      *(char**)(prev) = (char*)return_ptr;
+  }
+
+  total_avail_ += size;
+}
+
+char const* 
+Huge_page_pool::name()
+{
+  return "Huge_page_pool";
+}
+
+} // namespace vsip::impl
+
+} // namespace vsip
Index: src/vsip/core/parallel/local_map.hpp
===================================================================
--- src/vsip/core/parallel/local_map.hpp	(revision 191870)
+++ src/vsip/core/parallel/local_map.hpp	(working copy)
@@ -18,6 +18,7 @@
 #include <vsip/core/value_iterator.hpp>
 #include <vsip/core/parallel/services.hpp>
 #include <vsip/core/parallel/map_traits.hpp>
+#include <vsip/core/pool.hpp>
 
 
 
@@ -53,7 +54,7 @@
 
   // Constructor.
 public:
-  Local_map() {}
+  Local_map() : pool_(vsip::impl::default_pool) {}
 
   template <dimension_type Dim>
   Local_map(Local_or_global_map<Dim> const&) {}
@@ -122,7 +123,11 @@
   processor_type impl_proc_from_rank(index_type idx) const
     { assert(idx == 0); return local_processor(); }
 
-  // No member data.
+  impl::Pool* impl_pool() const { return pool_; }
+
+  // Member data.
+private:
+  impl::Pool* pool_;
 };
 
 namespace impl
Index: src/vsip/core/aligned_pool.cpp
===================================================================
--- src/vsip/core/aligned_pool.cpp	(revision 0)
+++ src/vsip/core/aligned_pool.cpp	(revision 0)
@@ -0,0 +1,66 @@
+/* Copyright (c) 2007 by CodeSourcery, LLC.  All rights reserved. */
+
+/** @file    vsip/core/aligned_pool.cpp
+    @author  Jules Bergmann
+    @date    2007-04-12
+    @brief   VSIPL++ Library: Memory allocation pool
+*/
+
+/***********************************************************************
+  Included Files
+***********************************************************************/
+
+#include <vsip/support.hpp>
+#include <vsip/core/config.hpp>
+#include <vsip/core/pool.hpp>
+#include <vsip/core/aligned_pool.hpp>
+
+
+
+/***********************************************************************
+  Declarations
+***********************************************************************/
+
+namespace vsip
+{
+
+namespace impl 
+{
+
+Aligned_pool::Aligned_pool()
+{}
+
+Aligned_pool::~Aligned_pool()
+{}
+
+
+void*
+Aligned_pool::allocate(size_t size)
+{
+  // If size == 0, allocate 1 byte.
+  if (size == 0)
+    size = 1;
+  
+  void* ptr = (void*)alloc_align<char>(align, size);
+  if (ptr == 0)
+    VSIP_IMPL_THROW(std::bad_alloc());
+  return ptr;
+}
+
+void
+Aligned_pool::deallocate(void* ptr, size_t size)
+{
+  free_align((char*)ptr);
+}
+
+char const*
+Aligned_pool::name()
+{
+  return "Aligned_pool";
+}
+  
+  
+
+} // namespace vsip::impl
+
+} // namespace vsip
Index: benchmarks/loop.hpp
===================================================================
--- benchmarks/loop.hpp	(revision 191870)
+++ benchmarks/loop.hpp	(working copy)
@@ -27,6 +27,7 @@
 #include <vsip/vector.hpp>
 #include <vsip/math.hpp>
 #include <vsip/parallel.hpp>
+#include <vsip/core/pool.hpp>
 
 #ifdef VSIP_IMPL_SOURCERY_VPP
 #  define PARALLEL_LOOP 1
@@ -133,7 +134,8 @@
     show_time_   (false),
     mode_        (sweep_mode),
     m_array_     (),
-    param_       ()
+    param_       (),
+    pool_        (0)
   {}
 
   template <typename Functor>
@@ -183,6 +185,7 @@
   bench_mode    mode_;
   std::vector<unsigned> m_array_;
   std::map<std::string, std::string> param_;
+  vsip::impl::Pool*                  pool_;
 };
 
 
@@ -284,6 +287,7 @@
   using vsip::Vector;
   using vsip::Dense;
   using vsip::row1_type;
+  using vsip::impl::Pool;
 
   size_t   loop, M;
   float    time;
@@ -321,7 +325,12 @@
     {
       old_loop = loop;
       BARRIER(comm);
-      fcn(M, loop, time);
+      {
+	Pool* cur_pool = vsip::impl::default_pool;
+	if (pool_) vsip::impl::default_pool = pool_;
+	fcn(M, loop, time);
+	vsip::impl::default_pool = cur_pool;
+      }
       BARRIER(comm);
 
       LOCAL(dist_time).put(0, time);
@@ -386,7 +395,12 @@
     for (unsigned j=0; j<n_time; ++j)
     {
       BARRIER(comm);
-      fcn(M, loop, time);
+      {
+	Pool* cur_pool = vsip::impl::default_pool;
+	if (pool_) vsip::impl::default_pool = pool_;
+	fcn(M, loop, time);
+	vsip::impl::default_pool = cur_pool;
+      }
       BARRIER(comm);
 
       LOCAL(dist_time).put(0, time);
@@ -479,6 +493,7 @@
   using vsip::Vector;
   using vsip::Dense;
   using vsip::row1_type;
+  using vsip::impl::Pool;
 
   size_t   loop, M;
   float    time;
@@ -532,7 +547,12 @@
     M = (1 << start_);
 
     BARRIER(comm);
-    fcn(M, loop, time);
+    {
+      Pool* cur_pool = vsip::impl::default_pool;
+      if (pool_) vsip::impl::default_pool = pool_;
+      fcn(M, loop, time);
+      vsip::impl::default_pool = cur_pool;
+    }
     BARRIER(comm);
 
     LOCAL(dist_time).put(0, time);
@@ -590,7 +610,12 @@
   COMMUNICATOR_TYPE& comm  = DEFAULT_COMMUNICATOR();
 
   BARRIER(comm);
-  fcn(M, loop, time);
+  {
+    vsip::impl::Pool* cur_pool = vsip::impl::default_pool;
+    if (pool_) vsip::impl::default_pool = pool_;
+    fcn(M, loop, time);
+    vsip::impl::default_pool = cur_pool;
+  }
   BARRIER(comm);
 }
 
Index: benchmarks/main.cpp
===================================================================
--- benchmarks/main.cpp	(revision 191870)
+++ benchmarks/main.cpp	(working copy)
@@ -23,6 +23,7 @@
 
 #include <vsip/initfin.hpp>
 #include <vsip/core/check_config.hpp>
+#include <vsip/core/huge_page_pool.hpp>
 
 #include "benchmarks.hpp"
 
@@ -156,6 +157,16 @@
       std::cout << vsip::impl::library_config();
       return 0;
     }
+    else if (!strcmp(argv[i], "-pool"))
+    {
+      ++i;
+      if (!strcmp(argv[i], "def"))
+	;
+      else if (!strcmp(argv[i], "huge"))
+	loop.pool_ = new vsip::impl::Huge_page_pool("/huge/benchmark.bin", 9);
+      else
+	std::cerr << "ERROR: Unknown pool type: " << argv[i] << std::endl;
+    }
     else
       std::cerr << "ERROR: Unknown argument: " << argv[i] << std::endl;
   }