template <size_t N, typename F> Vc_ALWAYS_INLINE void benchmark(F &&f) { TimeStampCounter tsc; auto cycles = tsc.cycles(); cycles = 0x7fffffff; for (int i = 0; i < 100; ++i) { tsc.start(); for (int j = 0; j < 10; ++j) { auto C = f(); unused(C); } tsc.stop(); cycles = std::min(cycles, tsc.cycles()); } //std::cout << cycles << " Cycles for " << N *N *(N + N - 1) << " FLOP => "; std::cout << std::setw(19) << std::setprecision(3) << double(N * N * (N + N - 1) * 10) / cycles; //<< " FLOP/cycle (" << variant << ")\n"; }
void Baker::createImage() { const int iHeight = m_image.height(); const int iWidth = m_image.width(); // Parameters Begin const float S = 4.f; const float nSteps[2] = { static_cast<float>(m_opt.steps[0] == -1 ? std::sqrt(iWidth) * iWidth : m_opt.steps[0]), static_cast<float>(m_opt.steps[1] == -1 ? std::sqrt(iHeight) * iHeight : m_opt.steps[1]) }; const int upperBound[3] = { m_opt.red[1], m_opt.green[1], m_opt.blue[1] }; const int lowerBound[3] = { m_opt.red[0], m_opt.green[0], m_opt.blue[0] }; int overallLowerBound = m_opt.it[0]; int maxIterations = m_opt.it[1];// maxOf(maxOf(overallLowerBound, upperBound[0]), maxOf(upperBound[1], upperBound[2])); float realMin = -2.102613f; float realMax = 1.200613f; float imagMin = 0.f; float imagMax = 1.23971f; // Parameters End TimeStampCounter timer; timer.start(); // helper constants const int overallUpperBound = maxOf(upperBound[0], maxOf(upperBound[1], upperBound[2])); const float maxX = static_cast<float>(iWidth ) - 1.f; const float maxY = static_cast<float>(iHeight) - 1.f; const float xFact = iWidth / m_width; const float yFact = iHeight / m_height; const float realStep = (realMax - realMin) / nSteps[0]; const float imagStep = (imagMax - imagMin) / nSteps[1]; Canvas canvas(iHeight, iWidth); #ifdef Scalar for (float real = realMin; real <= realMax; real += realStep) { m_progress.setValue(99.f * (real - realMin) / (realMax - realMin)); for (float imag = imagMin; imag <= imagMax; imag += imagStep) { Z c(real, imag); Z c2 = Z(1.08f * real + 0.15f, imag); if (fastNorm(Z(real + 1.f, imag)) < 0.06f || (std::real(c2) < 0.42f && fastNorm(c2) < 0.417f)) { continue; } Z z = c; int n; for (n = 0; n <= maxIterations && fastNorm(z) < S; ++n) { z = P(z, c); } if (n <= maxIterations && n >= overallLowerBound) { // point is outside of the Mandelbrot set and required enough (overallLowerBound) // iterations to reach the cut-off value S Z cn(real, -imag); Z zn = cn; z = c; for (int i = 0; i <= overallUpperBound; ++i) { const float y2 = (std::imag(z) - m_y) * yFact; const float yn2 = (std::imag(zn) - m_y) * yFact; if (y2 >= 0.f && y2 < maxY && yn2 >= 0.f && yn2 < maxY) { const float x2 = (std::real(z) - m_x) * xFact; if (x2 >= 0.f && x2 < maxX) { const int red = (i >= lowerBound[0] && i <= upperBound[0]) ? 1 : 0; const int green = (i >= lowerBound[1] && i <= upperBound[1]) ? 1 : 0; const int blue = (i >= lowerBound[2] && i <= upperBound[2]) ? 1 : 0; canvas.addDot(x2, y2 , red, green, blue); canvas.addDot(x2, yn2, red, green, blue); } } z = P(z, c); zn = P(zn, cn); if (fastNorm(z) >= S) { // optimization: skip some useless looping break; } } } } } #else const float imagStep2 = imagStep * float_v::Size; const float_v imagMin2 = imagMin + imagStep * static_cast<float_v>(int_v::IndexesFromZero()); for (float real = realMin; real <= realMax; real += realStep) { m_progress.setValue(99.f * (real - realMin) / (realMax - realMin)); for (float_v imag = imagMin2; all_of(imag <= imagMax); imag += imagStep2) { // FIXME: extra "tracks" if nSteps[1] is not a multiple of float_v::Size Z c(float_v(real), imag); Z c2 = Z(float_v(1.08f * real + 0.15f), imag); if (all_of(fastNorm(Z(float_v(real + 1.f), imag)) < 0.06f || (std::real(c2) < 0.42f && fastNorm(c2) < 0.417f))) { continue; } Z z = c; int_v n(Vc::Zero); int_m inside = fastNorm(z) < S; while (!(inside && n <= maxIterations).isEmpty()) { z = P(z, c); ++n(inside); inside &= fastNorm(z) < S; } inside |= n < overallLowerBound; if (inside.isFull()) { continue; } Z cn(float_v(real), -imag); Z zn = cn; z = c; for (int i = 0; i <= overallUpperBound; ++i) { const float_v y2 = (std::imag(z) - m_y) * yFact; const float_v yn2 = (std::imag(zn) - m_y) * yFact; const float_v x2 = (std::real(z) - m_x) * xFact; z = P(z, c); zn = P(zn, cn); const float_m drawMask = !inside && y2 >= 0.f && x2 >= 0.f && y2 < maxY && x2 < maxX && yn2 >= 0.f && yn2 < maxY; const int red = (i >= lowerBound[0] && i <= upperBound[0]) ? 1 : 0; const int green = (i >= lowerBound[1] && i <= upperBound[1]) ? 1 : 0; const int blue = (i >= lowerBound[2] && i <= upperBound[2]) ? 1 : 0; for(int j : where(drawMask)) { canvas.addDot(x2[j], y2 [j], red, green, blue); canvas.addDot(x2[j], yn2[j], red, green, blue); } if (all_of(fastNorm(z) >= S)) { // optimization: skip some useless looping break; } } } } #endif canvas.toQImage(&m_image); timer.stop(); m_progress.done(); qDebug() << timer.cycles() << "cycles"; if (m_filename.isEmpty()) { m_filename = QString("r%1-%2_g%3-%4_b%5-%6_s%7-%8_i%9-%10_%11x%12.png") .arg(lowerBound[0]).arg(upperBound[0]) .arg(lowerBound[1]).arg(upperBound[1]) .arg(lowerBound[2]).arg(upperBound[2]) .arg(nSteps[0]).arg(nSteps[1]) .arg(overallLowerBound).arg(maxIterations) .arg(m_image.width()).arg(m_image.height()); } m_image.save(m_filename); }