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.
<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(),
// ---------------------------------------------------------------------
//
-// 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
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
{
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)
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;
*/
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.
*/
#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
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;
}
#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;
{
// 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);
}
void
Vector<Number>::deallocate()
{
- _mm_free(val);
+ free(val);
val = 0;
}
#include <limits>
#include <sstream>
+#ifndef DEAL_II_MSVC
+# include <stdlib.h>
+#endif
+
#ifdef DEAL_II_MSVC
# include <winsock2.h>
#endif
}
+ 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();