Generators.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #pragma once
  2. #ifndef MANDELQUEUE_H_
  3. #define MANDELQUEUE_H_
  4. #include "QueueManager.h"
  5. #include "GenericMandelbrot.h"
  6. #include <omp.h>
  7. #include <cmath>
  8. #include <future>
  9. #include <cstdlib>
  10. #ifdef __APPLE__
  11. #include <OpenCL/cl.hpp>
  12. #else
  13. #include <CL/cl.hpp>
  14. #endif
  15. #include <immintrin.h>
  16. class ClGenerator : public MandelGenerator
  17. {
  18. cl::Device device;
  19. cl::Context context;
  20. cl::Program program;
  21. cl::CommandQueue queue;
  22. public:
  23. ClGenerator(void);
  24. ~ClGenerator(void) = default;
  25. //Bitmap<RGBColor> generate(const MandelInfo& info);
  26. Bitmap<float> generateRaw(const MandelInfo& info);
  27. std::future<Bitmap<RGBColor>> enqueueMandelbrot(long width, long height, float x, float y, float fwidth);
  28. };
  29. std::future<Bitmap<RGBColor>> createHPM();
  30. template<typename T>
  31. class CpuGenerator : public MandelGenerator
  32. {
  33. public:
  34. Bitmap<float> generateRaw(const MandelInfo& info)
  35. {
  36. const MandelViewport& view = info.view;
  37. Bitmap<float> res{ info.bWidth, info.bHeight };
  38. omp_set_num_threads(2 * omp_get_num_procs());
  39. #pragma omp parallel for
  40. for (int j = 0; j < res.height; j++) {
  41. T y = T(view.y) + T(j) * view.height / res.height;
  42. for (::size_t i = 0; i < res.width; i++) {
  43. T x = T(view.x) + T(i) * view.width / res.width;
  44. res.get(i, j) = iterate<T>(x, y, info.maxIter);
  45. }
  46. }
  47. return res;
  48. }
  49. };
  50. template<>
  51. inline Bitmap<float> CpuGenerator<double>::generateRaw(const MandelInfo& info)
  52. {
  53. using T = double;
  54. const MandelViewport& view = info.view;
  55. Bitmap<float> res{ info.bWidth, info.bHeight };
  56. omp_set_num_threads(2 * omp_get_num_procs());
  57. #pragma omp parallel for
  58. for (long j = 0; j < res.height; j++) {
  59. T y = T(view.y) + T(j) * view.height / res.height;
  60. long i = 0;
  61. for (i; i < res.width; i += 4) {
  62. __m256d xs = {
  63. double(view.x) + double(i) * view.width / res.width,
  64. double(view.x) + double(i + 1) * view.width / res.width,
  65. double(view.x) + double(i + 2) * view.width / res.width,
  66. double(view.x) + double(i + 3) * view.width / res.width
  67. };
  68. int itRes[4] = {0, 0, 0, 0};
  69. __m256d threshold = {16.0, 16.0, 16.0, 16.0};
  70. __m256d counter = {0, 0, 0, 0};
  71. __m256d adder = {1, 1, 1, 1};
  72. __m256d ys = {y, y, y, y};
  73. __m256d a = xs;
  74. __m256d b = ys;
  75. for (int k = 0; k < info.maxIter; k++) {
  76. __m256d aa = _mm256_mul_pd(a, a);
  77. __m256d bb = _mm256_mul_pd(b, b);
  78. __m256d abab = _mm256_mul_pd(a, b); abab = _mm256_add_pd(abab, abab);
  79. a = _mm256_add_pd(_mm256_sub_pd(aa, bb), xs);
  80. b = _mm256_add_pd(abab, ys);
  81. __m256i cmp = _mm256_castpd_si256(_mm256_cmp_pd(_mm256_add_pd(aa, bb), threshold, _CMP_LE_OQ));
  82. adder = _mm256_and_pd(adder, _mm256_castsi256_pd(cmp));
  83. counter = _mm256_add_pd(counter, adder);
  84. if (_mm256_testz_si256(cmp, cmp) != 0) {
  85. break;
  86. }
  87. }
  88. double data[8];
  89. void* aligned = data;
  90. ::size_t length = sizeof data;
  91. std::align(32, 4 * sizeof(double), aligned, length);
  92. double* ftRes = static_cast<double*>(aligned);
  93. _mm256_store_pd(ftRes, counter);
  94. for (int k = 0; k < 4; k++)
  95. res.get(i + k, j) = ftRes[k] > 0 ? float(ftRes[k]) : info.maxIter;
  96. }
  97. }
  98. return res;
  99. }
  100. template<>
  101. inline Bitmap<float> CpuGenerator<float>::generateRaw(const MandelInfo& info)
  102. {
  103. using T = float;
  104. const MandelViewport& view = info.view;
  105. Bitmap<float> res{ info.bWidth, info.bHeight };
  106. omp_set_num_threads(2 * omp_get_num_procs());
  107. #pragma omp parallel for
  108. for (long j = 0; j < res.height; j++) {
  109. T y = T(view.y) + T(j) * view.height / res.height;
  110. long i = 0;
  111. for (i; i < res.width; i += 8) {
  112. __m256 xs = {
  113. float(view.x + double(i) * view.width / res.width),
  114. float(view.x + double(i + 1) * view.width / res.width),
  115. float(view.x + double(i + 2) * view.width / res.width),
  116. float(view.x + double(i + 3) * view.width / res.width),
  117. float(view.x + double(i + 4) * view.width / res.width),
  118. float(view.x + double(i + 5) * view.width / res.width),
  119. float(view.x + double(i + 6) * view.width / res.width),
  120. float(view.x + double(i + 7) * view.width / res.width)
  121. };
  122. __m256 counter = {0, 0, 0, 0, 0, 0, 0, 0};
  123. __m256 adder = {1, 1, 1, 1, 1, 1, 1, 1};
  124. __m256 threshold = {16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f};
  125. __m256 ys = {y, y, y, y, y, y, y, y};
  126. __m256 a = xs;
  127. __m256 b = ys;
  128. for (int k = 0; k < info.maxIter; k++) {
  129. __m256 aa = _mm256_mul_ps(a, a);
  130. __m256 bb = _mm256_mul_ps(b, b);
  131. __m256 abab = _mm256_mul_ps(a, b); abab = _mm256_add_ps(abab, abab);
  132. a = _mm256_add_ps(_mm256_sub_ps(aa, bb), xs);
  133. b = _mm256_add_ps(abab, ys);
  134. __m256i cmp = _mm256_castps_si256(_mm256_cmp_ps(_mm256_add_ps(aa, bb), threshold, _CMP_LE_OQ));
  135. adder = _mm256_and_ps(adder, _mm256_castsi256_ps(cmp));
  136. counter = _mm256_add_ps(counter, adder);
  137. if (_mm256_testz_si256(cmp, cmp) != 0) {
  138. break;
  139. }
  140. }
  141. float data[16];
  142. void* aligned = data;
  143. ::size_t length = sizeof data;
  144. std::align(32, 8 * sizeof(float), aligned, length);
  145. float* ftRes = static_cast<float*>(aligned);
  146. _mm256_store_ps(ftRes, counter);
  147. for (int k = 0; k < 8; k++)
  148. res.get(i + k, j) = ftRes[k] > 0 ? ftRes[k] : info.maxIter;
  149. }
  150. }
  151. return res;
  152. }
  153. #endif // MANDELQUEUE_H_