dynalloc.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla
  7. // Public License v. 2.0. If a copy of the MPL was not distributed
  8. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. #include "main.h"
  10. #if EIGEN_MAX_ALIGN_BYTES>0
  11. #define ALIGNMENT EIGEN_MAX_ALIGN_BYTES
  12. #else
  13. #define ALIGNMENT 1
  14. #endif
  15. typedef Matrix<float,16,1> Vector16f;
  16. typedef Matrix<float,8,1> Vector8f;
  17. void check_handmade_aligned_malloc()
  18. {
  19. for(int i = 1; i < 1000; i++)
  20. {
  21. char *p = (char*)internal::handmade_aligned_malloc(i);
  22. VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
  23. // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
  24. for(int j = 0; j < i; j++) p[j]=0;
  25. internal::handmade_aligned_free(p);
  26. }
  27. }
  28. void check_aligned_malloc()
  29. {
  30. for(int i = ALIGNMENT; i < 1000; i++)
  31. {
  32. char *p = (char*)internal::aligned_malloc(i);
  33. VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
  34. // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
  35. for(int j = 0; j < i; j++) p[j]=0;
  36. internal::aligned_free(p);
  37. }
  38. }
  39. void check_aligned_new()
  40. {
  41. for(int i = ALIGNMENT; i < 1000; i++)
  42. {
  43. float *p = internal::aligned_new<float>(i);
  44. VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
  45. // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
  46. for(int j = 0; j < i; j++) p[j]=0;
  47. internal::aligned_delete(p,i);
  48. }
  49. }
  50. void check_aligned_stack_alloc()
  51. {
  52. for(int i = ALIGNMENT; i < 400; i++)
  53. {
  54. ei_declare_aligned_stack_constructed_variable(float,p,i,0);
  55. VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
  56. // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
  57. for(int j = 0; j < i; j++) p[j]=0;
  58. }
  59. }
  60. // test compilation with both a struct and a class...
  61. struct MyStruct
  62. {
  63. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  64. char dummychar;
  65. Vector16f avec;
  66. };
  67. class MyClassA
  68. {
  69. public:
  70. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  71. char dummychar;
  72. Vector16f avec;
  73. };
  74. template<typename T> void check_dynaligned()
  75. {
  76. // TODO have to be updated once we support multiple alignment values
  77. if(T::SizeAtCompileTime % ALIGNMENT == 0)
  78. {
  79. T* obj = new T;
  80. VERIFY(T::NeedsToAlign==1);
  81. VERIFY(internal::UIntPtr(obj)%ALIGNMENT==0);
  82. delete obj;
  83. }
  84. }
  85. template<typename T> void check_custom_new_delete()
  86. {
  87. {
  88. T* t = new T;
  89. delete t;
  90. }
  91. {
  92. std::size_t N = internal::random<std::size_t>(1,10);
  93. T* t = new T[N];
  94. delete[] t;
  95. }
  96. #if EIGEN_MAX_ALIGN_BYTES>0 && (!EIGEN_HAS_CXX17_OVERALIGN)
  97. {
  98. T* t = static_cast<T *>((T::operator new)(sizeof(T)));
  99. (T::operator delete)(t, sizeof(T));
  100. }
  101. {
  102. T* t = static_cast<T *>((T::operator new)(sizeof(T)));
  103. (T::operator delete)(t);
  104. }
  105. #endif
  106. }
  107. EIGEN_DECLARE_TEST(dynalloc)
  108. {
  109. // low level dynamic memory allocation
  110. CALL_SUBTEST(check_handmade_aligned_malloc());
  111. CALL_SUBTEST(check_aligned_malloc());
  112. CALL_SUBTEST(check_aligned_new());
  113. CALL_SUBTEST(check_aligned_stack_alloc());
  114. for (int i=0; i<g_repeat*100; ++i)
  115. {
  116. CALL_SUBTEST( check_custom_new_delete<Vector4f>() );
  117. CALL_SUBTEST( check_custom_new_delete<Vector2f>() );
  118. CALL_SUBTEST( check_custom_new_delete<Matrix4f>() );
  119. CALL_SUBTEST( check_custom_new_delete<MatrixXi>() );
  120. }
  121. // check static allocation, who knows ?
  122. #if EIGEN_MAX_STATIC_ALIGN_BYTES
  123. for (int i=0; i<g_repeat*100; ++i)
  124. {
  125. CALL_SUBTEST(check_dynaligned<Vector4f>() );
  126. CALL_SUBTEST(check_dynaligned<Vector2d>() );
  127. CALL_SUBTEST(check_dynaligned<Matrix4f>() );
  128. CALL_SUBTEST(check_dynaligned<Vector4d>() );
  129. CALL_SUBTEST(check_dynaligned<Vector4i>() );
  130. CALL_SUBTEST(check_dynaligned<Vector8f>() );
  131. CALL_SUBTEST(check_dynaligned<Vector16f>() );
  132. }
  133. {
  134. MyStruct foo0; VERIFY(internal::UIntPtr(foo0.avec.data())%ALIGNMENT==0);
  135. MyClassA fooA; VERIFY(internal::UIntPtr(fooA.avec.data())%ALIGNMENT==0);
  136. }
  137. // dynamic allocation, single object
  138. for (int i=0; i<g_repeat*100; ++i)
  139. {
  140. MyStruct *foo0 = new MyStruct(); VERIFY(internal::UIntPtr(foo0->avec.data())%ALIGNMENT==0);
  141. MyClassA *fooA = new MyClassA(); VERIFY(internal::UIntPtr(fooA->avec.data())%ALIGNMENT==0);
  142. delete foo0;
  143. delete fooA;
  144. }
  145. // dynamic allocation, array
  146. const int N = 10;
  147. for (int i=0; i<g_repeat*100; ++i)
  148. {
  149. MyStruct *foo0 = new MyStruct[N]; VERIFY(internal::UIntPtr(foo0->avec.data())%ALIGNMENT==0);
  150. MyClassA *fooA = new MyClassA[N]; VERIFY(internal::UIntPtr(fooA->avec.data())%ALIGNMENT==0);
  151. delete[] foo0;
  152. delete[] fooA;
  153. }
  154. #endif
  155. }