|  | @@ -24,58 +24,99 @@ void CpuGenerator<float, mnd::X86_AVX_512, parallel>::generate(const mnd::Mandel
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      const float dppf = float(view.width / info.bWidth);
 |  |      const float dppf = float(view.width / info.bWidth);
 | 
											
												
													
														|  |      const float viewxf = float(view.x);
 |  |      const float viewxf = float(view.x);
 | 
											
												
													
														|  | -    __m512 viewx = { viewxf, viewxf, viewxf, viewxf, viewxf, viewxf, viewxf, viewxf,
 |  | 
 | 
											
												
													
														|  | -                     viewxf, viewxf, viewxf, viewxf, viewxf, viewxf, viewxf, viewxf };
 |  | 
 | 
											
												
													
														|  | -    __m512 dpp = { dppf, dppf, dppf, dppf, dppf, dppf, dppf, dppf,
 |  | 
 | 
											
												
													
														|  | -                   dppf, dppf, dppf, dppf, dppf, dppf, dppf, dppf };
 |  | 
 | 
											
												
													
														|  | 
 |  | +    __m512 viewx = _mm512_set1_ps(viewxf);
 | 
											
												
													
														|  | 
 |  | +    __m512 dpp = _mm512_set1_ps(dppf);
 | 
											
												
													
														|  | 
 |  | +    __m512 enumerate = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
 | 
											
												
													
														|  | 
 |  | +    __m512 two = _mm512_set1_ps(2);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      if constexpr(parallel)
 |  |      if constexpr(parallel)
 | 
											
												
													
														|  |          omp_set_num_threads(omp_get_num_procs());
 |  |          omp_set_num_threads(omp_get_num_procs());
 | 
											
												
													
														|  |  #pragma omp parallel for schedule(static, 1) if (parallel)
 |  |  #pragma omp parallel for schedule(static, 1) if (parallel)
 | 
											
												
													
														|  |      for (long j = 0; j < info.bHeight; j++) {
 |  |      for (long j = 0; j < info.bHeight; j++) {
 | 
											
												
													
														|  |          T y = T(view.y + double(j) * view.height / info.bHeight);
 |  |          T y = T(view.y + double(j) * view.height / info.bHeight);
 | 
											
												
													
														|  | -        __m512 ys = { y, y, y, y, y, y, y, y, y, y, y, y, y, y, y, y };
 |  | 
 | 
											
												
													
														|  | -        for (long i = 0; i < info.bWidth; i += 16) {
 |  | 
 | 
											
												
													
														|  | -            __m512 pixc = { float(i), float(i + 1), float(i + 2), float(i + 3), float(i + 4), float(i + 5), float(i + 6), float(i + 7),
 |  | 
 | 
											
												
													
														|  | -                            float(i + 8), float(i + 9), float(i + 10), float(i + 11), float(i + 12), float(i + 13), float(i + 14), float(i + 15) };
 |  | 
 | 
											
												
													
														|  | -            __m512 xs = _mm512_fmadd_ps(dpp, pixc, viewx);
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            __m512 counter = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 |  | 
 | 
											
												
													
														|  | -            __m512 adder = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
 |  | 
 | 
											
												
													
														|  | -            __m512 two = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2  };
 |  | 
 | 
											
												
													
														|  | -            __m512 resultsa = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 |  | 
 | 
											
												
													
														|  | -            __m512 resultsb = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            __m512 threshold = { 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f,
 |  | 
 | 
											
												
													
														|  | -                                 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f };
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            __m512 a = xs;
 |  | 
 | 
											
												
													
														|  | -            __m512 b = ys;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        __m512 ys = _mm512_set1_ps(y);
 | 
											
												
													
														|  | 
 |  | +        for (long i = 0; i < info.bWidth; i += 2 * 16) {
 | 
											
												
													
														|  | 
 |  | +            __m512 pixc0 = _mm512_add_ps(_mm512_set1_ps(float(i)), enumerate);
 | 
											
												
													
														|  | 
 |  | +            __m512 pixc1 = _mm512_add_ps(_mm512_set1_ps(float(i + 16)), enumerate);
 | 
											
												
													
														|  | 
 |  | +            //__m512 pixc2 = _mm512_add_ps(_mm512_set1_ps(float(i + 32)), enumerate);
 | 
											
												
													
														|  | 
 |  | +            __m512 xs0 = _mm512_fmadd_ps(dpp, pixc0, viewx);
 | 
											
												
													
														|  | 
 |  | +            __m512 xs1 = _mm512_fmadd_ps(dpp, pixc1, viewx);
 | 
											
												
													
														|  | 
 |  | +            //__m512 xs2 = _mm512_fmadd_ps(dpp, pixc2, viewx);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            __m512 counter0 = _mm512_setzero_ps();
 | 
											
												
													
														|  | 
 |  | +            __m512 counter1 = _mm512_setzero_ps();
 | 
											
												
													
														|  | 
 |  | +            //__m512 counter2 = _mm512_setzero_ps();
 | 
											
												
													
														|  | 
 |  | +            __m512 adder0 = _mm512_set1_ps(1);
 | 
											
												
													
														|  | 
 |  | +            __m512 adder1 = _mm512_set1_ps(1);
 | 
											
												
													
														|  | 
 |  | +            //__m512 adder2 = _mm512_set1_ps(1);
 | 
											
												
													
														|  | 
 |  | +            __m512 resultsa0 = _mm512_setzero_ps();
 | 
											
												
													
														|  | 
 |  | +            __m512 resultsa1 = _mm512_setzero_ps();
 | 
											
												
													
														|  | 
 |  | +            //__m512 resultsa2 = _mm512_setzero_ps();
 | 
											
												
													
														|  | 
 |  | +            __m512 resultsb0 = _mm512_setzero_ps();
 | 
											
												
													
														|  | 
 |  | +            __m512 resultsb1 = _mm512_setzero_ps();
 | 
											
												
													
														|  | 
 |  | +            //__m512 resultsb2 = _mm512_setzero_ps();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            __m512 threshold = _mm512_set1_ps(16);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            __m512 a0 = xs0;
 | 
											
												
													
														|  | 
 |  | +            __m512 a1 = xs1;
 | 
											
												
													
														|  | 
 |  | +            //__m512 a2 = xs2;
 | 
											
												
													
														|  | 
 |  | +            __m512 b0 = ys;
 | 
											
												
													
														|  | 
 |  | +            __m512 b1 = ys;
 | 
											
												
													
														|  | 
 |  | +            //__m512 b2 = ys;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              if (info.smooth) {
 |  |              if (info.smooth) {
 | 
											
												
													
														|  |                  for (int k = 0; k < info.maxIter; k++) {
 |  |                  for (int k = 0; k < info.maxIter; k++) {
 | 
											
												
													
														|  | -                    __m512 aa = _mm512_mul_ps(a, a);
 |  | 
 | 
											
												
													
														|  | -                    __m512 abab = _mm512_mul_ps(a, b);
 |  | 
 | 
											
												
													
														|  | -                    __mmask16 cmp = _mm512_cmp_ps_mask(_mm512_fmadd_ps(b, b, aa), threshold, _CMP_LE_OQ);
 |  | 
 | 
											
												
													
														|  | -                    a = _mm512_sub_ps(aa, _mm512_fmsub_ps(b, b, xs));
 |  | 
 | 
											
												
													
														|  | -                    b = _mm512_fmadd_ps(two, abab, ys);
 |  | 
 | 
											
												
													
														|  | -                    counter = _mm512_mask_add_ps(counter, cmp, counter, adder);
 |  | 
 | 
											
												
													
														|  | -                    resultsa = _mm512_mask_blend_ps(cmp, resultsa, a);
 |  | 
 | 
											
												
													
														|  | -                    resultsb = _mm512_mask_blend_ps(cmp, resultsb, b);
 |  | 
 | 
											
												
													
														|  | -                    if (cmp == 0) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    __m512 aa0 = _mm512_mul_ps(a0, a0);
 | 
											
												
													
														|  | 
 |  | +                    __m512 aa1 = _mm512_mul_ps(a1, a1);
 | 
											
												
													
														|  | 
 |  | +                    //__m512 aa2 = _mm512_mul_ps(a2, a2);
 | 
											
												
													
														|  | 
 |  | +                    __m512 abab0 = _mm512_mul_ps(a0, b0);
 | 
											
												
													
														|  | 
 |  | +                    __m512 abab1 = _mm512_mul_ps(a1, b1);
 | 
											
												
													
														|  | 
 |  | +                    //__m512 abab2 = _mm512_mul_ps(a2, b2);
 | 
											
												
													
														|  | 
 |  | +                    __mmask16 cmp0 = _mm512_cmp_ps_mask(_mm512_fmadd_ps(b0, b0, aa0), threshold, _CMP_LE_OQ);
 | 
											
												
													
														|  | 
 |  | +                    __mmask16 cmp1 = _mm512_cmp_ps_mask(_mm512_fmadd_ps(b1, b1, aa1), threshold, _CMP_LE_OQ);
 | 
											
												
													
														|  | 
 |  | +                    //__mmask16 cmp2 = _mm512_cmp_ps_mask(_mm512_fmadd_ps(b2, b2, aa2), threshold, _CMP_LE_OQ);
 | 
											
												
													
														|  | 
 |  | +                    a0 = _mm512_sub_ps(aa0, _mm512_fmsub_ps(b0, b0, xs0));
 | 
											
												
													
														|  | 
 |  | +                    a1 = _mm512_sub_ps(aa1, _mm512_fmsub_ps(b1, b1, xs1));
 | 
											
												
													
														|  | 
 |  | +                    //a2 = _mm512_sub_ps(aa2, _mm512_fmsub_ps(b2, b2, xs2));
 | 
											
												
													
														|  | 
 |  | +                    b0 = _mm512_fmadd_ps(two, abab0, ys);
 | 
											
												
													
														|  | 
 |  | +                    b1 = _mm512_fmadd_ps(two, abab1, ys);
 | 
											
												
													
														|  | 
 |  | +                    //b2 = _mm512_fmadd_ps(two, abab2, ys);
 | 
											
												
													
														|  | 
 |  | +                    counter0 = _mm512_mask_add_ps(counter0, cmp0, counter0, adder0);
 | 
											
												
													
														|  | 
 |  | +                    counter1 = _mm512_mask_add_ps(counter1, cmp1, counter1, adder1);
 | 
											
												
													
														|  | 
 |  | +                    //counter2 = _mm512_mask_add_ps(counter2, cmp2, counter2, adder2);
 | 
											
												
													
														|  | 
 |  | +                    resultsa0 = _mm512_mask_blend_ps(cmp0, resultsa0, a0);
 | 
											
												
													
														|  | 
 |  | +                    resultsa1 = _mm512_mask_blend_ps(cmp1, resultsa1, a1);
 | 
											
												
													
														|  | 
 |  | +                    //resultsa2 = _mm512_mask_blend_ps(cmp2, resultsa2, a2);
 | 
											
												
													
														|  | 
 |  | +                    resultsb0 = _mm512_mask_blend_ps(cmp0, resultsb0, b0);
 | 
											
												
													
														|  | 
 |  | +                    resultsb1 = _mm512_mask_blend_ps(cmp1, resultsb1, b1);
 | 
											
												
													
														|  | 
 |  | +                    //resultsb2 = _mm512_mask_blend_ps(cmp2, resultsb2, b2);
 | 
											
												
													
														|  | 
 |  | +                    if (cmp0 == 0 && cmp1 == 0 /*&& cmp2 == 0*/) {
 | 
											
												
													
														|  |                          break;
 |  |                          break;
 | 
											
												
													
														|  |                      }
 |  |                      }
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |              else {
 |  |              else {
 | 
											
												
													
														|  |                  for (int k = 0; k < info.maxIter; k++) {
 |  |                  for (int k = 0; k < info.maxIter; k++) {
 | 
											
												
													
														|  | -                    __m512 aa = _mm512_mul_ps(a, a);
 |  | 
 | 
											
												
													
														|  | -                    __m512 abab = _mm512_mul_ps(a, b);
 |  | 
 | 
											
												
													
														|  | -                    __mmask16 cmp = _mm512_cmp_ps_mask(_mm512_fmadd_ps(b, b, aa), threshold, _CMP_LE_OQ);
 |  | 
 | 
											
												
													
														|  | -                    a = _mm512_sub_ps(aa, _mm512_fmsub_ps(b, b, xs));
 |  | 
 | 
											
												
													
														|  | -                    b = _mm512_fmadd_ps(two, abab, ys);
 |  | 
 | 
											
												
													
														|  | -                    counter = _mm512_mask_add_ps(counter, cmp, counter, adder);
 |  | 
 | 
											
												
													
														|  | -                    if (cmp == 0) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    __m512 aa0 = _mm512_mul_ps(a0, a0);
 | 
											
												
													
														|  | 
 |  | +                    __m512 aa1 = _mm512_mul_ps(a1, a1);
 | 
											
												
													
														|  | 
 |  | +                    //__m512 aa2 = _mm512_mul_ps(a2, a2);
 | 
											
												
													
														|  | 
 |  | +                    __m512 abab0 = _mm512_mul_ps(a0, b0);
 | 
											
												
													
														|  | 
 |  | +                    __m512 abab1 = _mm512_mul_ps(a1, b1);
 | 
											
												
													
														|  | 
 |  | +                    //__m512 abab2 = _mm512_mul_ps(a2, b2);
 | 
											
												
													
														|  | 
 |  | +                    __mmask16 cmp0 = _mm512_cmp_ps_mask(_mm512_fmadd_ps(b0, b0, aa0), threshold, _CMP_LE_OQ);
 | 
											
												
													
														|  | 
 |  | +                    __mmask16 cmp1 = _mm512_cmp_ps_mask(_mm512_fmadd_ps(b1, b1, aa1), threshold, _CMP_LE_OQ);
 | 
											
												
													
														|  | 
 |  | +                    //__mmask16 cmp2 = _mm512_cmp_ps_mask(_mm512_fmadd_ps(b2, b2, aa2), threshold, _CMP_LE_OQ);
 | 
											
												
													
														|  | 
 |  | +                    a0 = _mm512_sub_ps(aa0, _mm512_fmsub_ps(b0, b0, xs0));
 | 
											
												
													
														|  | 
 |  | +                    a1 = _mm512_sub_ps(aa1, _mm512_fmsub_ps(b1, b1, xs1));
 | 
											
												
													
														|  | 
 |  | +                    //a2 = _mm512_sub_ps(aa2, _mm512_fmsub_ps(b2, b2, xs2));
 | 
											
												
													
														|  | 
 |  | +                    b0 = _mm512_fmadd_ps(two, abab0, ys);
 | 
											
												
													
														|  | 
 |  | +                    b1 = _mm512_fmadd_ps(two, abab1, ys);
 | 
											
												
													
														|  | 
 |  | +                    //b2 = _mm512_fmadd_ps(two, abab2, ys);
 | 
											
												
													
														|  | 
 |  | +                    counter0 = _mm512_mask_add_ps(counter0, cmp0, counter0, adder0);
 | 
											
												
													
														|  | 
 |  | +                    counter1 = _mm512_mask_add_ps(counter1, cmp1, counter1, adder1);
 | 
											
												
													
														|  | 
 |  | +                    //counter2 = _mm512_mask_add_ps(counter2, cmp2, counter2, adder2);
 | 
											
												
													
														|  | 
 |  | +                    if (cmp0 == 0 && cmp1 == 0 /*&& cmp2 == 0*/) {
 | 
											
												
													
														|  |                          break;
 |  |                          break;
 | 
											
												
													
														|  |                      }
 |  |                      }
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
										
											
												
													
														|  | @@ -83,21 +124,27 @@ void CpuGenerator<float, mnd::X86_AVX_512, parallel>::generate(const mnd::Mandel
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              auto alignVec = [](float* data) -> float* {
 |  |              auto alignVec = [](float* data) -> float* {
 | 
											
												
													
														|  |                  void* aligned = data;
 |  |                  void* aligned = data;
 | 
											
												
													
														|  | -                ::size_t length = 64 * sizeof(float);
 |  | 
 | 
											
												
													
														|  | 
 |  | +                ::size_t length = 3 * 64 * sizeof(float);
 | 
											
												
													
														|  |                  std::align(64, 48 * sizeof(float), aligned, length);
 |  |                  std::align(64, 48 * sizeof(float), aligned, length);
 | 
											
												
													
														|  |                  return static_cast<float*>(aligned);
 |  |                  return static_cast<float*>(aligned);
 | 
											
												
													
														|  |              };
 |  |              };
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            float resData[64];
 |  | 
 | 
											
												
													
														|  | 
 |  | +            float resData[3 * 64];
 | 
											
												
													
														|  |              float* ftRes = alignVec(resData);
 |  |              float* ftRes = alignVec(resData);
 | 
											
												
													
														|  | -            float* resa = ftRes + 16;
 |  | 
 | 
											
												
													
														|  | -            float* resb = ftRes + 32;
 |  | 
 | 
											
												
													
														|  | -            _mm512_store_ps(ftRes, counter);
 |  | 
 | 
											
												
													
														|  | 
 |  | +            float* resa = ftRes + 3 * 16;
 | 
											
												
													
														|  | 
 |  | +            float* resb = ftRes + 6 * 16;
 | 
											
												
													
														|  | 
 |  | +            _mm512_store_ps(ftRes, counter0);
 | 
											
												
													
														|  | 
 |  | +            _mm512_store_ps(ftRes + 16, counter1);
 | 
											
												
													
														|  | 
 |  | +            //_mm512_store_ps(ftRes + 32, counter2);
 | 
											
												
													
														|  |              if (info.smooth) {
 |  |              if (info.smooth) {
 | 
											
												
													
														|  | -                _mm512_store_ps(resa, resultsa);
 |  | 
 | 
											
												
													
														|  | -                _mm512_store_ps(resb, resultsb);
 |  | 
 | 
											
												
													
														|  | 
 |  | +                _mm512_store_ps(resa, resultsa0);
 | 
											
												
													
														|  | 
 |  | +                _mm512_store_ps(resa + 16, resultsa1);
 | 
											
												
													
														|  | 
 |  | +                //_mm512_store_ps(resa + 32, resultsa2);
 | 
											
												
													
														|  | 
 |  | +                _mm512_store_ps(resb, resultsb0);
 | 
											
												
													
														|  | 
 |  | +                _mm512_store_ps(resb + 16, resultsb1);
 | 
											
												
													
														|  | 
 |  | +                //_mm512_store_ps(resb + 32, resultsb2);
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  | -            for (int k = 0; k < 16 && i + k < info.bWidth; k++) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +            for (int k = 0; k < 2 * 16 && i + k < info.bWidth; k++) {
 | 
											
												
													
														|  |                  if (info.smooth) {
 |  |                  if (info.smooth) {
 | 
											
												
													
														|  |                      data[i + k + j * info.bWidth] = ftRes[k] <= 0 ? info.maxIter :
 |  |                      data[i + k + j * info.bWidth] = ftRes[k] <= 0 ? info.maxIter :
 | 
											
												
													
														|  |                          ftRes[k] >= info.maxIter ? info.maxIter :
 |  |                          ftRes[k] >= info.maxIter ? info.maxIter :
 |