]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Avoid the use of _mm_malloc/_mm_free in favor of posix_memalign. 808/head 831/head
authorWolfgang Bangerth <bangerth@math.tamu.edu>
Wed, 15 Apr 2015 18:32:46 +0000 (13:32 -0500)
committerWolfgang Bangerth <bangerth@math.tamu.edu>
Fri, 17 Apr 2015 22:14:50 +0000 (17:14 -0500)
This has the additional advantage that free() can be used and we don't have to be
special on both sides of memory allocation/deallocation.

doc/news/changes.h
include/deal.II/base/aligned_vector.h
include/deal.II/base/utilities.h
include/deal.II/lac/parallel_vector.templates.h
include/deal.II/lac/vector.templates.h
source/base/utilities.cc

index d3ef58962dafd8beaeed439eded8edadc684fc29..3590125d3f40934c0e9b4bf54a37d7438230b956 100644 (file)
@@ -352,6 +352,16 @@ inconvenience this causes.
 
 
 <ol>
+  <li> Fixed: There were a number of places in the library where we unconditionally
+  called functions <code>_mm_malloc()/_mm_free()</code> to allocate and free
+  memory with a known alignment. This function, however, is only available on
+  systems with x86 or x64_64 compatible processors. These places have now been
+  replaced by calling <code>posix_memalign()</code> instead, a function that
+  should be more widely available.
+  <br>
+  (Wolfgang Bangerth, 2015/04/15)
+  </li>
+
   <li> Deprecated: The library uses functions such as CellAccessor::subdomain_id(),
   TriaAccessor::manifold_id(), etc, but used the deviant spelling
   TriaAccessor::boundary_indicator(), TriaAccessor::set_boundary_indicator(),
index 534510b3b7f9309cbc460b36aa6fd60ade5948f0..ed1dcc97bd4f247de6693964eaab985078b8c044 100644 (file)
@@ -1,6 +1,6 @@
 // ---------------------------------------------------------------------
 //
-// Copyright (C) 2011 - 2014 by the deal.II authors
+// Copyright (C) 2011 - 2015 by the deal.II authors
 //
 // This file is part of the deal.II library.
 //
 #include <deal.II/base/std_cxx11/type_traits.h>
 #include <deal.II/base/exceptions.h>
 #include <deal.II/base/memory_consumption.h>
+#include <deal.II/base/utilities.h>
 #include <deal.II/base/parallel.h>
 #include <boost/serialization/array.hpp>
 #include <boost/serialization/split_member.hpp>
 
 #include <cstring>
 
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
-#include <emmintrin.h>
-#endif
-
 
 
 DEAL_II_NAMESPACE_OPEN
@@ -538,16 +535,10 @@ AlignedVector<T>::reserve (const size_type size_alloc)
 
       const size_type size_actual_allocate = new_size * sizeof(T);
 
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
-
       // allocate and align along 64-byte boundaries (this is enough for all
       // levels of vectorization currently supported by deal.II)
-      T *new_data = static_cast<T *>(_mm_malloc (size_actual_allocate, 64));
-#else
-      T *new_data = static_cast<T *>(malloc (size_actual_allocate));
-#endif
-      if (new_data == 0)
-        throw std::bad_alloc();
+      T *new_data;
+      Utilities::System::posix_memalign ((void **)&new_data, 64, size_actual_allocate);
 
       // copy data in case there was some content before and release the old
       // memory with the function corresponding to the one used for allocating
@@ -558,11 +549,7 @@ AlignedVector<T>::reserve (const size_type size_alloc)
         {
           dealii::internal::AlignedVectorMove<T>(new_data, new_data + old_size,
                                                  _data);
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
-          _mm_free(new_data);
-#else
           free(new_data);
-#endif
         }
     }
   else if (size_alloc == 0)
@@ -582,11 +569,7 @@ AlignedVector<T>::clear ()
         while (_end_data != _data)
           (--_end_data)->~T();
 
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
-      _mm_free(_data);
-#else
       free(_data);
-#endif
     }
   _data = 0;
   _end_data = 0;
index 7a45c412da4777f5e2868e5c7f7f49d9a62b86e2..4200224e60647ef3b95f4cf574538e23d81da251 100644 (file)
@@ -375,6 +375,22 @@ namespace Utilities
      */
     std::string get_time ();
 
+    /**
+     * Call the system function posix_memalign, or a replacement function if not
+     * available, to allocate memory with a certain minimal alignment. The
+     * first argument will then return a pointer to this memory block that can
+     * be released later on through a standard <code>free</code> call.
+     *
+     * @param memptr The address of a pointer variable that will after this call
+     *   point to the allocated memory.
+     * @param alignment The minimal alignment of the memory block, in bytes.
+     * @param size The size of the memory block to be allocated, in bytes.
+     *
+     * @note This function checks internally for error codes, rather than
+     *   leaving this task to the calling site.
+     */
+    void posix_memalign (void **memptr, size_t alignment, size_t size);
+
     /**
      * @deprecated Use Utilities::MPI::job_supports_mpi() instead.
      */
index eb3495e21fd4d1c0b26230eb9b09070ad1dc2baf..1511dd8985679b34cd09442b0469e27c6f5a4d51 100644 (file)
 #include <deal.II/lac/petsc_parallel_vector.h>
 #include <deal.II/lac/trilinos_vector.h>
 
-#ifndef _MSC_VER
-#  include <mm_malloc.h>
-#endif
-
 DEAL_II_NAMESPACE_OPEN
 
 
@@ -61,14 +57,16 @@ namespace parallel
           Assert (((allocated_size > 0 && val != 0) ||
                    val == 0), ExcInternalError());
           if (val != 0)
-            _mm_free(val);
-          val = static_cast<Number *>(_mm_malloc (sizeof(Number)*new_alloc_size, 64));
+            free(val);
+
+          Utilities::System::posix_memalign ((void **)&val, 64, sizeof(Number)*new_alloc_size);
+
           allocated_size = new_alloc_size;
         }
       else if (new_alloc_size == 0)
         {
           if (val != 0)
-            _mm_free(val);
+            free(val);
           val = 0;
           allocated_size = 0;
         }
index bcfe8b6190478fb627e3a7ba3ebc7a620a587bbe..eef22765074a21c76ba34d72e11ed94f7bcfb6dd 100644 (file)
 #include <iostream>
 #include <iomanip>
 
-#ifndef _MSC_VER
-#  include <mm_malloc.h>
-#endif
-
 DEAL_II_NAMESPACE_OPEN
 
 
-
 namespace internal
 {
   typedef types::global_dof_index size_type;
@@ -2050,8 +2045,9 @@ Vector<Number>::allocate()
 {
   // make sure that we don't create a memory leak
   Assert (val == 0, ExcInternalError());
-  val = static_cast<Number *>(_mm_malloc (sizeof(Number)*max_vec_size, 64));
-  Assert (val != 0, ExcOutOfMemory());
+
+  // then allocate memory with the proper alignment requirements of 64 bytes
+  Utilities::System::posix_memalign ((void **)&val, 64, sizeof(Number)*max_vec_size);
 }
 
 
@@ -2060,7 +2056,7 @@ template <typename Number>
 void
 Vector<Number>::deallocate()
 {
-  _mm_free(val);
+  free(val);
   val = 0;
 }
 
index 579a725049ea48021ed510c7ee2789048dcb92c2..e3d872b5b6e8e04fe0c9bb1e2c76b90ba64843b1 100644 (file)
 #include <limits>
 #include <sstream>
 
+#ifndef DEAL_II_MSVC
+#  include <stdlib.h>
+#endif
+
 #ifdef DEAL_II_MSVC
 #  include <winsock2.h>
 #endif
@@ -628,6 +632,23 @@ namespace Utilities
     }
 
 
+    void posix_memalign (void **memptr, size_t alignment, size_t size)
+    {
+#ifndef DEAL_II_MSVC
+      const int ierr = ::posix_memalign (memptr, alignment, size);
+
+      AssertThrow (ierr == 0, ExcOutOfMemory());
+      AssertThrow (*memptr != 0, ExcOutOfMemory());
+#else
+      // Windows does not appear to have posix_memalign. just use the
+      // regular malloc in that case
+      *memptr = malloc (size);
+      AssertThrow (*memptr != 0, ExcOutOfMemory());
+#endif
+    }
+
+
+
     bool job_supports_mpi ()
     {
       return Utilities::MPI::job_supports_mpi();

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.