Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.

This commit is contained in:
Rob Armstrong
2025-03-27 10:30:07 -07:00
parent 2cd58fbc9a
commit ceab6e8bcc
782 changed files with 107230 additions and 106548 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -26,369 +26,504 @@
*/
#include <stdio.h>
#include "helper_cuda.h"
#include "Mandelbrot_kernel.h"
#include "Mandelbrot_kernel.cuh"
#include "Mandelbrot_kernel.h"
#include "helper_cuda.h"
// The Mandelbrot CUDA GPU thread function
template <class T>
__global__ void Mandelbrot0(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const T xOff, const T yOff,
const T xJP, const T yJP, const T scale,
const uchar4 colors, const int frame,
const int animationFrame, const int gridWidth,
const int numBlocks, const bool isJ) {
// loop until all blocks completed
for (unsigned int blockIndex = blockIdx.x; blockIndex < numBlocks;
blockIndex += gridDim.x) {
unsigned int blockX = blockIndex % gridWidth;
unsigned int blockY = blockIndex / gridWidth;
__global__ void Mandelbrot0(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const T xOff,
const T yOff,
const T xJP,
const T yJP,
const T scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const int gridWidth,
const int numBlocks,
const bool isJ)
{
// loop until all blocks completed
for (unsigned int blockIndex = blockIdx.x; blockIndex < numBlocks; blockIndex += gridDim.x) {
unsigned int blockX = blockIndex % gridWidth;
unsigned int blockY = blockIndex / gridWidth;
// process this block
const int ix = blockDim.x * blockX + threadIdx.x;
const int iy = blockDim.y * blockY + threadIdx.y;
// process this block
const int ix = blockDim.x * blockX + threadIdx.x;
const int iy = blockDim.y * blockY + threadIdx.y;
if ((ix < imageW) && (iy < imageH)) {
// Calculate the location
const T xPos = (T)ix * scale + xOff;
const T yPos = (T)iy * scale + yOff;
if ((ix < imageW) && (iy < imageH)) {
// Calculate the location
const T xPos = (T)ix * scale + xOff;
const T yPos = (T)iy * scale + yOff;
// Calculate the Mandelbrot index for the current location
int m = CalcMandelbrot<T>(xPos, yPos, xJP, yJP, crunch, isJ);
// int m = blockIdx.x; // uncomment to see scheduling
// order
m = m > 0 ? crunch - m : 0;
// Calculate the Mandelbrot index for the current location
int m = CalcMandelbrot<T>(xPos, yPos, xJP, yJP, crunch, isJ);
// int m = blockIdx.x; // uncomment to see scheduling
// order
m = m > 0 ? crunch - m : 0;
// Convert the Mandelbrot index into a color
uchar4 color;
// Convert the Mandelbrot index into a color
uchar4 color;
if (m) {
m += animationFrame;
color.x = m * colors.x;
color.y = m * colors.y;
color.z = m * colors.z;
} else {
color.x = 0;
color.y = 0;
color.z = 0;
}
if (m) {
m += animationFrame;
color.x = m * colors.x;
color.y = m * colors.y;
color.z = m * colors.z;
}
else {
color.x = 0;
color.y = 0;
color.z = 0;
}
// Output the pixel
int pixel = imageW * iy + ix;
// Output the pixel
int pixel = imageW * iy + ix;
if (frame == 0) {
color.w = 0;
dst[pixel] = color;
} else {
int frame1 = frame + 1;
int frame2 = frame1 / 2;
dst[pixel].x = (dst[pixel].x * frame + color.x + frame2) / frame1;
dst[pixel].y = (dst[pixel].y * frame + color.y + frame2) / frame1;
dst[pixel].z = (dst[pixel].z * frame + color.z + frame2) / frame1;
}
if (frame == 0) {
color.w = 0;
dst[pixel] = color;
}
else {
int frame1 = frame + 1;
int frame2 = frame1 / 2;
dst[pixel].x = (dst[pixel].x * frame + color.x + frame2) / frame1;
dst[pixel].y = (dst[pixel].y * frame + color.y + frame2) / frame1;
dst[pixel].z = (dst[pixel].z * frame + color.z + frame2) / frame1;
}
}
}
}
} // Mandelbrot0
} // Mandelbrot0
// The Mandelbrot CUDA GPU thread function (double single version)
__global__ void MandelbrotDS0(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const float xOff0,
const float xOff1, const float yOff0,
const float yOff1, const float xJP,
const float yJP, const float scale,
const uchar4 colors, const int frame,
const int animationFrame, const int gridWidth,
const int numBlocks, const bool isJ) {
// loop until all blocks completed
for (unsigned int blockIndex = blockIdx.x; blockIndex < numBlocks;
blockIndex += gridDim.x) {
unsigned int blockX = blockIndex % gridWidth;
unsigned int blockY = blockIndex / gridWidth;
__global__ void MandelbrotDS0(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const float xOff0,
const float xOff1,
const float yOff0,
const float yOff1,
const float xJP,
const float yJP,
const float scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const int gridWidth,
const int numBlocks,
const bool isJ)
{
// loop until all blocks completed
for (unsigned int blockIndex = blockIdx.x; blockIndex < numBlocks; blockIndex += gridDim.x) {
unsigned int blockX = blockIndex % gridWidth;
unsigned int blockY = blockIndex / gridWidth;
// process this block
const int ix = blockDim.x * blockX + threadIdx.x;
const int iy = blockDim.y * blockY + threadIdx.y;
// process this block
const int ix = blockDim.x * blockX + threadIdx.x;
const int iy = blockDim.y * blockY + threadIdx.y;
if ((ix < imageW) && (iy < imageH)) {
// Calculate the location
float xPos0 = (float)ix * scale;
float xPos1 = 0.0f;
float yPos0 = (float)iy * scale;
float yPos1 = 0.0f;
dsadd(xPos0, xPos1, xPos0, xPos1, xOff0, xOff1);
dsadd(yPos0, yPos1, yPos0, yPos1, yOff0, yOff1);
if ((ix < imageW) && (iy < imageH)) {
// Calculate the location
float xPos0 = (float)ix * scale;
float xPos1 = 0.0f;
float yPos0 = (float)iy * scale;
float yPos1 = 0.0f;
dsadd(xPos0, xPos1, xPos0, xPos1, xOff0, xOff1);
dsadd(yPos0, yPos1, yPos0, yPos1, yOff0, yOff1);
// Calculate the Mandelbrot index for the current location
int m =
CalcMandelbrotDS(xPos0, xPos1, yPos0, yPos1, xJP, yJP, crunch, isJ);
m = m > 0 ? crunch - m : 0;
// Calculate the Mandelbrot index for the current location
int m = CalcMandelbrotDS(xPos0, xPos1, yPos0, yPos1, xJP, yJP, crunch, isJ);
m = m > 0 ? crunch - m : 0;
// Convert the Mandelbrot index into a color
uchar4 color;
// Convert the Mandelbrot index into a color
uchar4 color;
if (m) {
m += animationFrame;
color.x = m * colors.x;
color.y = m * colors.y;
color.z = m * colors.z;
} else {
color.x = 0;
color.y = 0;
color.z = 0;
}
if (m) {
m += animationFrame;
color.x = m * colors.x;
color.y = m * colors.y;
color.z = m * colors.z;
}
else {
color.x = 0;
color.y = 0;
color.z = 0;
}
// Output the pixel
int pixel = imageW * iy + ix;
// Output the pixel
int pixel = imageW * iy + ix;
if (frame == 0) {
color.w = 0;
dst[pixel] = color;
} else {
int frame1 = frame + 1;
int frame2 = frame1 / 2;
dst[pixel].x = (dst[pixel].x * frame + color.x + frame2) / frame1;
dst[pixel].y = (dst[pixel].y * frame + color.y + frame2) / frame1;
dst[pixel].z = (dst[pixel].z * frame + color.z + frame2) / frame1;
}
if (frame == 0) {
color.w = 0;
dst[pixel] = color;
}
else {
int frame1 = frame + 1;
int frame2 = frame1 / 2;
dst[pixel].x = (dst[pixel].x * frame + color.x + frame2) / frame1;
dst[pixel].y = (dst[pixel].y * frame + color.y + frame2) / frame1;
dst[pixel].z = (dst[pixel].z * frame + color.z + frame2) / frame1;
}
}
}
}
} // MandelbrotDS0
} // MandelbrotDS0
// The Mandelbrot secondary AA pass CUDA GPU thread function
template <class T>
__global__ void Mandelbrot1(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const T xOff, const T yOff,
const T xJP, const T yJP, const T scale,
const uchar4 colors, const int frame,
const int animationFrame, const int gridWidth,
const int numBlocks, const bool isJ) {
// loop until all blocks completed
for (unsigned int blockIndex = blockIdx.x; blockIndex < numBlocks;
blockIndex += gridDim.x) {
unsigned int blockX = blockIndex % gridWidth;
unsigned int blockY = blockIndex / gridWidth;
__global__ void Mandelbrot1(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const T xOff,
const T yOff,
const T xJP,
const T yJP,
const T scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const int gridWidth,
const int numBlocks,
const bool isJ)
{
// loop until all blocks completed
for (unsigned int blockIndex = blockIdx.x; blockIndex < numBlocks; blockIndex += gridDim.x) {
unsigned int blockX = blockIndex % gridWidth;
unsigned int blockY = blockIndex / gridWidth;
// process this block
const int ix = blockDim.x * blockX + threadIdx.x;
const int iy = blockDim.y * blockY + threadIdx.y;
// process this block
const int ix = blockDim.x * blockX + threadIdx.x;
const int iy = blockDim.y * blockY + threadIdx.y;
if ((ix < imageW) && (iy < imageH)) {
// Get the current pixel color
int pixel = imageW * iy + ix;
uchar4 pixelColor = dst[pixel];
int count = 0;
if ((ix < imageW) && (iy < imageH)) {
// Get the current pixel color
int pixel = imageW * iy + ix;
uchar4 pixelColor = dst[pixel];
int count = 0;
// Search for pixels out of tolerance surrounding the current pixel
if (ix > 0) {
count += CheckColors(pixelColor, dst[pixel - 1]);
}
// Search for pixels out of tolerance surrounding the current pixel
if (ix > 0) {
count += CheckColors(pixelColor, dst[pixel - 1]);
}
if (ix + 1 < imageW) {
count += CheckColors(pixelColor, dst[pixel + 1]);
}
if (ix + 1 < imageW) {
count += CheckColors(pixelColor, dst[pixel + 1]);
}
if (iy > 0) {
count += CheckColors(pixelColor, dst[pixel - imageW]);
}
if (iy > 0) {
count += CheckColors(pixelColor, dst[pixel - imageW]);
}
if (iy + 1 < imageH) {
count += CheckColors(pixelColor, dst[pixel + imageW]);
}
if (iy + 1 < imageH) {
count += CheckColors(pixelColor, dst[pixel + imageW]);
}
if (count) {
// Calculate the location
const T xPos = (T)ix * scale + xOff;
const T yPos = (T)iy * scale + yOff;
if (count) {
// Calculate the location
const T xPos = (T)ix * scale + xOff;
const T yPos = (T)iy * scale + yOff;
// Calculate the Mandelbrot index for the current location
int m = CalcMandelbrot(xPos, yPos, xJP, yJP, crunch, isJ);
m = m > 0 ? crunch - m : 0;
// Calculate the Mandelbrot index for the current location
int m = CalcMandelbrot(xPos, yPos, xJP, yJP, crunch, isJ);
m = m > 0 ? crunch - m : 0;
// Convert the Mandelbrot index into a color
uchar4 color;
// Convert the Mandelbrot index into a color
uchar4 color;
if (m) {
m += animationFrame;
color.x = m * colors.x;
color.y = m * colors.y;
color.z = m * colors.z;
} else {
color.x = 0;
color.y = 0;
color.z = 0;
if (m) {
m += animationFrame;
color.x = m * colors.x;
color.y = m * colors.y;
color.z = m * colors.z;
}
else {
color.x = 0;
color.y = 0;
color.z = 0;
}
// Output the pixel
int frame1 = frame + 1;
int frame2 = frame1 / 2;
dst[pixel].x = (pixelColor.x * frame + color.x + frame2) / frame1;
dst[pixel].y = (pixelColor.y * frame + color.y + frame2) / frame1;
dst[pixel].z = (pixelColor.z * frame + color.z + frame2) / frame1;
}
}
// Output the pixel
int frame1 = frame + 1;
int frame2 = frame1 / 2;
dst[pixel].x = (pixelColor.x * frame + color.x + frame2) / frame1;
dst[pixel].y = (pixelColor.y * frame + color.y + frame2) / frame1;
dst[pixel].z = (pixelColor.z * frame + color.z + frame2) / frame1;
}
}
}
} // Mandelbrot1
} // Mandelbrot1
// The Mandelbrot secondary AA pass CUDA GPU thread function (double single
// version)
__global__ void MandelbrotDS1(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const float xOff0,
const float xOff1, const float yOff0,
const float yOff1, const float xJP,
const float yJP, const float scale,
const uchar4 colors, const int frame,
const int animationFrame, const int gridWidth,
const int numBlocks, const bool isJ) {
// loop until all blocks completed
for (unsigned int blockIndex = blockIdx.x; blockIndex < numBlocks;
blockIndex += gridDim.x) {
unsigned int blockX = blockIndex % gridWidth;
unsigned int blockY = blockIndex / gridWidth;
__global__ void MandelbrotDS1(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const float xOff0,
const float xOff1,
const float yOff0,
const float yOff1,
const float xJP,
const float yJP,
const float scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const int gridWidth,
const int numBlocks,
const bool isJ)
{
// loop until all blocks completed
for (unsigned int blockIndex = blockIdx.x; blockIndex < numBlocks; blockIndex += gridDim.x) {
unsigned int blockX = blockIndex % gridWidth;
unsigned int blockY = blockIndex / gridWidth;
// process this block
const int ix = blockDim.x * blockX + threadIdx.x;
const int iy = blockDim.y * blockY + threadIdx.y;
// process this block
const int ix = blockDim.x * blockX + threadIdx.x;
const int iy = blockDim.y * blockY + threadIdx.y;
if ((ix < imageW) && (iy < imageH)) {
// Get the current pixel color
int pixel = imageW * iy + ix;
uchar4 pixelColor = dst[pixel];
int count = 0;
if ((ix < imageW) && (iy < imageH)) {
// Get the current pixel color
int pixel = imageW * iy + ix;
uchar4 pixelColor = dst[pixel];
int count = 0;
// Search for pixels out of tolerance surrounding the current pixel
if (ix > 0) {
count += CheckColors(pixelColor, dst[pixel - 1]);
}
// Search for pixels out of tolerance surrounding the current pixel
if (ix > 0) {
count += CheckColors(pixelColor, dst[pixel - 1]);
}
if (ix + 1 < imageW) {
count += CheckColors(pixelColor, dst[pixel + 1]);
}
if (ix + 1 < imageW) {
count += CheckColors(pixelColor, dst[pixel + 1]);
}
if (iy > 0) {
count += CheckColors(pixelColor, dst[pixel - imageW]);
}
if (iy > 0) {
count += CheckColors(pixelColor, dst[pixel - imageW]);
}
if (iy + 1 < imageH) {
count += CheckColors(pixelColor, dst[pixel + imageW]);
}
if (iy + 1 < imageH) {
count += CheckColors(pixelColor, dst[pixel + imageW]);
}
if (count) {
// Calculate the location
float xPos0 = (float)ix * scale;
float xPos1 = 0.0f;
float yPos0 = (float)iy * scale;
float yPos1 = 0.0f;
dsadd(xPos0, xPos1, xPos0, xPos1, xOff0, xOff1);
dsadd(yPos0, yPos1, yPos0, yPos1, yOff0, yOff1);
if (count) {
// Calculate the location
float xPos0 = (float)ix * scale;
float xPos1 = 0.0f;
float yPos0 = (float)iy * scale;
float yPos1 = 0.0f;
dsadd(xPos0, xPos1, xPos0, xPos1, xOff0, xOff1);
dsadd(yPos0, yPos1, yPos0, yPos1, yOff0, yOff1);
// Calculate the Mandelbrot index for the current location
int m =
CalcMandelbrotDS(xPos0, xPos1, yPos0, yPos1, xJP, yJP, crunch, isJ);
m = m > 0 ? crunch - m : 0;
// Calculate the Mandelbrot index for the current location
int m = CalcMandelbrotDS(xPos0, xPos1, yPos0, yPos1, xJP, yJP, crunch, isJ);
m = m > 0 ? crunch - m : 0;
// Convert the Mandelbrot index into a color
uchar4 color;
// Convert the Mandelbrot index into a color
uchar4 color;
if (m) {
m += animationFrame;
color.x = m * colors.x;
color.y = m * colors.y;
color.z = m * colors.z;
} else {
color.x = 0;
color.y = 0;
color.z = 0;
if (m) {
m += animationFrame;
color.x = m * colors.x;
color.y = m * colors.y;
color.z = m * colors.z;
}
else {
color.x = 0;
color.y = 0;
color.z = 0;
}
// Output the pixel
int frame1 = frame + 1;
int frame2 = frame1 / 2;
dst[pixel].x = (pixelColor.x * frame + color.x + frame2) / frame1;
dst[pixel].y = (pixelColor.y * frame + color.y + frame2) / frame1;
dst[pixel].z = (pixelColor.z * frame + color.z + frame2) / frame1;
}
}
// Output the pixel
int frame1 = frame + 1;
int frame2 = frame1 / 2;
dst[pixel].x = (pixelColor.x * frame + color.x + frame2) / frame1;
dst[pixel].y = (pixelColor.y * frame + color.y + frame2) / frame1;
dst[pixel].z = (pixelColor.z * frame + color.z + frame2) / frame1;
}
}
}
} // MandelbrotDS1
} // MandelbrotDS1
// The host CPU Mandelbrot thread spawner
void RunMandelbrot0(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const double xOff, const double yOff,
const double xjp, const double yjp, const double scale,
const uchar4 colors, const int frame,
const int animationFrame, const int mode, const int numSMs,
const bool isJ, int version) {
dim3 threads(BLOCKDIM_X, BLOCKDIM_Y);
dim3 grid(iDivUp(imageW, BLOCKDIM_X), iDivUp(imageH, BLOCKDIM_Y));
void RunMandelbrot0(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const double xOff,
const double yOff,
const double xjp,
const double yjp,
const double scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const int mode,
const int numSMs,
const bool isJ,
int version)
{
dim3 threads(BLOCKDIM_X, BLOCKDIM_Y);
dim3 grid(iDivUp(imageW, BLOCKDIM_X), iDivUp(imageH, BLOCKDIM_Y));
int numWorkerBlocks = numSMs;
int numWorkerBlocks = numSMs;
switch (mode) {
switch (mode) {
default:
case 0:
Mandelbrot0<float><<<numWorkerBlocks, threads>>>(
dst, imageW, imageH, crunch, (float)xOff, (float)yOff, (float)xjp,
(float)yjp, (float)scale, colors, frame, animationFrame, grid.x,
grid.x * grid.y, isJ);
break;
Mandelbrot0<float><<<numWorkerBlocks, threads>>>(dst,
imageW,
imageH,
crunch,
(float)xOff,
(float)yOff,
(float)xjp,
(float)yjp,
(float)scale,
colors,
frame,
animationFrame,
grid.x,
grid.x * grid.y,
isJ);
break;
case 1:
float x0, x1, y0, y1;
dsdeq(x0, x1, xOff);
dsdeq(y0, y1, yOff);
MandelbrotDS0<<<numWorkerBlocks, threads>>>(
dst, imageW, imageH, crunch, x0, x1, y0, y1, (float)xjp, (float)yjp,
(float)scale, colors, frame, animationFrame, grid.x, grid.x * grid.y,
isJ);
break;
float x0, x1, y0, y1;
dsdeq(x0, x1, xOff);
dsdeq(y0, y1, yOff);
MandelbrotDS0<<<numWorkerBlocks, threads>>>(dst,
imageW,
imageH,
crunch,
x0,
x1,
y0,
y1,
(float)xjp,
(float)yjp,
(float)scale,
colors,
frame,
animationFrame,
grid.x,
grid.x * grid.y,
isJ);
break;
case 2:
Mandelbrot0<double><<<numWorkerBlocks, threads>>>(
dst, imageW, imageH, crunch, xOff, yOff, xjp, yjp, scale, colors,
frame, animationFrame, grid.x, grid.x * grid.y, isJ);
break;
}
Mandelbrot0<double><<<numWorkerBlocks, threads>>>(dst,
imageW,
imageH,
crunch,
xOff,
yOff,
xjp,
yjp,
scale,
colors,
frame,
animationFrame,
grid.x,
grid.x * grid.y,
isJ);
break;
}
getLastCudaError("Mandelbrot0 kernel execution failed.\n");
} // RunMandelbrot0
getLastCudaError("Mandelbrot0 kernel execution failed.\n");
} // RunMandelbrot0
// The host CPU Mandelbrot thread spawner
void RunMandelbrot1(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const double xOff, const double yOff,
const double xjp, const double yjp, const double scale,
const uchar4 colors, const int frame,
const int animationFrame, const int mode, const int numSMs,
const bool isJ, int version) {
dim3 threads(BLOCKDIM_X, BLOCKDIM_Y);
dim3 grid(iDivUp(imageW, BLOCKDIM_X), iDivUp(imageH, BLOCKDIM_Y));
void RunMandelbrot1(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const double xOff,
const double yOff,
const double xjp,
const double yjp,
const double scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const int mode,
const int numSMs,
const bool isJ,
int version)
{
dim3 threads(BLOCKDIM_X, BLOCKDIM_Y);
dim3 grid(iDivUp(imageW, BLOCKDIM_X), iDivUp(imageH, BLOCKDIM_Y));
int numWorkerBlocks = numSMs;
int numWorkerBlocks = numSMs;
switch (mode) {
switch (mode) {
default:
case 0:
Mandelbrot1<float><<<numWorkerBlocks, threads>>>(
dst, imageW, imageH, crunch, (float)xOff, (float)yOff, (float)xjp,
(float)yjp, (float)scale, colors, frame, animationFrame, grid.x,
grid.x * grid.y, isJ);
break;
Mandelbrot1<float><<<numWorkerBlocks, threads>>>(dst,
imageW,
imageH,
crunch,
(float)xOff,
(float)yOff,
(float)xjp,
(float)yjp,
(float)scale,
colors,
frame,
animationFrame,
grid.x,
grid.x * grid.y,
isJ);
break;
case 1:
float x0, x1, y0, y1;
dsdeq(x0, x1, xOff);
dsdeq(y0, y1, yOff);
MandelbrotDS1<<<numWorkerBlocks, threads>>>(
dst, imageW, imageH, crunch, x0, x1, y0, y1, (float)xjp, (float)yjp,
(float)scale, colors, frame, animationFrame, grid.x, grid.x * grid.y,
isJ);
break;
float x0, x1, y0, y1;
dsdeq(x0, x1, xOff);
dsdeq(y0, y1, yOff);
MandelbrotDS1<<<numWorkerBlocks, threads>>>(dst,
imageW,
imageH,
crunch,
x0,
x1,
y0,
y1,
(float)xjp,
(float)yjp,
(float)scale,
colors,
frame,
animationFrame,
grid.x,
grid.x * grid.y,
isJ);
break;
case 2:
Mandelbrot1<double><<<numWorkerBlocks, threads>>>(
dst, imageW, imageH, crunch, xOff, yOff, xjp, yjp, scale, colors,
frame, animationFrame, grid.x, grid.x * grid.y, isJ);
break;
}
Mandelbrot1<double><<<numWorkerBlocks, threads>>>(dst,
imageW,
imageH,
crunch,
xOff,
yOff,
xjp,
yjp,
scale,
colors,
frame,
animationFrame,
grid.x,
grid.x * grid.y,
isJ);
break;
}
getLastCudaError("Mandelbrot1 kernel execution failed.\n");
} // RunMandelbrot1
getLastCudaError("Mandelbrot1 kernel execution failed.\n");
} // RunMandelbrot1

View File

@@ -30,253 +30,313 @@
#define ABS(n) ((n) < 0 ? -(n) : (n))
/* dfloat class declaration */
class dfloat {
private:
float val[2];
class dfloat
{
private:
float val[2];
public:
dfloat() { val[0] = val[1] = 0; }
dfloat(float a, float b) {
val[0] = a;
val[1] = b;
}
dfloat(double b);
inline float operator[](unsigned idx) const { return val[idx]; }
public:
dfloat() { val[0] = val[1] = 0; }
dfloat(float a, float b)
{
val[0] = a;
val[1] = b;
}
dfloat(double b);
inline float operator[](unsigned idx) const { return val[idx]; }
};
inline dfloat operator+(const dfloat &dsa, const dfloat &dsb);
inline dfloat operator-(const dfloat &dsa, const dfloat &dsb);
inline dfloat operator*(const dfloat &dsa, const dfloat &dsb);
inline int operator<(const dfloat &a, float b) { return a[0] < b; }
inline int operator<(const dfloat &a, float b) { return a[0] < b; }
// The core Mandelbrot calculation function template
template <class T>
inline int CalcMandelbrot(const T xPos, const T yPos, const T xJParam,
const T yJParam, const int crunch,
const bool isJulia) {
T x, y, xx, yy, xC, yC;
int i = crunch;
inline int
CalcMandelbrot(const T xPos, const T yPos, const T xJParam, const T yJParam, const int crunch, const bool isJulia)
{
T x, y, xx, yy, xC, yC;
int i = crunch;
if (isJulia) {
xC = xJParam;
yC = yJParam;
y = yPos;
x = xPos;
yy = y * y;
xx = x * x;
} else {
xC = xPos;
yC = yPos;
x = y = 0;
xx = yy = 0;
}
if (isJulia) {
xC = xJParam;
yC = yJParam;
y = yPos;
x = xPos;
yy = y * y;
xx = x * x;
}
else {
xC = xPos;
yC = yPos;
x = y = 0;
xx = yy = 0;
}
while (--i && (xx + yy < 4.0f)) {
y = x * y + x * y + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
}
while (--i && (xx + yy < 4.0f)) {
y = x * y + x * y + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
}
return i;
} // CalcMandelbrot
return i;
} // CalcMandelbrot
inline void updatePixel(uchar4 &dst, const uchar4 &color, int frame) {
int frame1 = frame + 1;
int frame2 = frame1 / 2;
dst.x = (dst.x * frame + color.x + frame2) / frame1;
dst.y = (dst.y * frame + color.y + frame2) / frame1;
dst.z = (dst.z * frame + color.z + frame2) / frame1;
inline void updatePixel(uchar4 &dst, const uchar4 &color, int frame)
{
int frame1 = frame + 1;
int frame2 = frame1 / 2;
dst.x = (dst.x * frame + color.x + frame2) / frame1;
dst.y = (dst.y * frame + color.y + frame2) / frame1;
dst.z = (dst.z * frame + color.z + frame2) / frame1;
}
inline void setColor(uchar4 &dst, const uchar4 &colors, int &m,
const int animationFrame) {
if (m == 0) {
dst.x = 0;
dst.y = 0;
dst.z = 0;
return;
}
inline void setColor(uchar4 &dst, const uchar4 &colors, int &m, const int animationFrame)
{
if (m == 0) {
dst.x = 0;
dst.y = 0;
dst.z = 0;
return;
}
m += animationFrame;
dst.x = m * colors.x;
dst.y = m * colors.y;
dst.z = m * colors.z;
m += animationFrame;
dst.x = m * colors.x;
dst.y = m * colors.y;
dst.z = m * colors.z;
}
template <class T, class T_>
void runMandelbrotGold0(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const T xOff, const T yOff,
const T xJParam, const T yJParam, const T scale,
const uchar4 colors, const int frame,
const int animationFrame, const bool isJulia) {
for (int iy = 0; iy < imageH; iy++)
for (int ix = 0; ix < imageW; ix++) {
// Calculate the location
const T_ xPos = (T)ix * scale + xOff;
const T_ yPos = (T)iy * scale + yOff;
void runMandelbrotGold0(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const T xOff,
const T yOff,
const T xJParam,
const T yJParam,
const T scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const bool isJulia)
{
for (int iy = 0; iy < imageH; iy++)
for (int ix = 0; ix < imageW; ix++) {
// Calculate the location
const T_ xPos = (T)ix * scale + xOff;
const T_ yPos = (T)iy * scale + yOff;
// Calculate the Mandelbrot index for the current location
int m = CalcMandelbrot<T_>(xPos, yPos, xJParam, yJParam, crunch, isJulia);
m = m > 0 ? crunch - m : 0;
// Calculate the Mandelbrot index for the current location
int m = CalcMandelbrot<T_>(xPos, yPos, xJParam, yJParam, crunch, isJulia);
m = m > 0 ? crunch - m : 0;
// Convert the Mandelbrot index into a color
uchar4 color;
// Convert the Mandelbrot index into a color
uchar4 color;
setColor(color, colors, m, animationFrame);
setColor(color, colors, m, animationFrame);
// Output the pixel
int pixel = imageW * iy + ix;
// Output the pixel
int pixel = imageW * iy + ix;
if (frame == 0) {
color.w = 0;
dst[pixel] = color;
} else
updatePixel(dst[pixel], color, frame);
}
if (frame == 0) {
color.w = 0;
dst[pixel] = color;
}
else
updatePixel(dst[pixel], color, frame);
}
} // runMandelbrotGold0_
} // runMandelbrotGold0_
// Determine if two pixel colors are within tolerance
inline int CheckColors(const uchar4 &color0, const uchar4 &color1) {
int x = color1.x - color0.x;
int y = color1.y - color0.y;
int z = color1.z - color0.z;
return (ABS(x) > 10) || (ABS(y) > 10) || (ABS(z) > 10);
} // CheckColors
inline int CheckColors(const uchar4 &color0, const uchar4 &color1)
{
int x = color1.x - color0.x;
int y = color1.y - color0.y;
int z = color1.z - color0.z;
return (ABS(x) > 10) || (ABS(y) > 10) || (ABS(z) > 10);
} // CheckColors
template <class T, class T_>
void runMandelbrotGold1(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const T xOff, const T yOff,
const T xJParam, const T yJParam, const T scale,
const uchar4 colors, const int frame,
const int animationFrame, const bool isJulia) {
for (int iy = 0; iy < imageH; iy++)
for (int ix = 0; ix < imageW; ix++) {
// Get the current pixel color
int pixel = imageW * iy + ix;
uchar4 pixelColor = dst[pixel];
int count = 0;
void runMandelbrotGold1(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const T xOff,
const T yOff,
const T xJParam,
const T yJParam,
const T scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const bool isJulia)
{
for (int iy = 0; iy < imageH; iy++)
for (int ix = 0; ix < imageW; ix++) {
// Get the current pixel color
int pixel = imageW * iy + ix;
uchar4 pixelColor = dst[pixel];
int count = 0;
// Search for pixels out of tolerance surrounding the current pixel
if (ix > 0) count += CheckColors(pixelColor, dst[pixel - 1]);
// Search for pixels out of tolerance surrounding the current pixel
if (ix > 0)
count += CheckColors(pixelColor, dst[pixel - 1]);
if (ix + 1 < imageW) count += CheckColors(pixelColor, dst[pixel + 1]);
if (ix + 1 < imageW)
count += CheckColors(pixelColor, dst[pixel + 1]);
if (iy > 0) count += CheckColors(pixelColor, dst[pixel - imageW]);
if (iy > 0)
count += CheckColors(pixelColor, dst[pixel - imageW]);
if (iy + 1 < imageH)
count += CheckColors(pixelColor, dst[pixel + imageW]);
if (iy + 1 < imageH)
count += CheckColors(pixelColor, dst[pixel + imageW]);
if (count) {
// Calculate the location
const T_ xPos = (T)ix * scale + xOff;
const T_ yPos = (T)iy * scale + yOff;
if (count) {
// Calculate the location
const T_ xPos = (T)ix * scale + xOff;
const T_ yPos = (T)iy * scale + yOff;
// Calculate the Mandelbrot index for the current location
int m =
CalcMandelbrot<T_>(xPos, yPos, xJParam, yJParam, crunch, isJulia);
m = m > 0 ? crunch - m : 0;
// Calculate the Mandelbrot index for the current location
int m = CalcMandelbrot<T_>(xPos, yPos, xJParam, yJParam, crunch, isJulia);
m = m > 0 ? crunch - m : 0;
// Convert the Mandelbrot index into a color
uchar4 color;
// Convert the Mandelbrot index into a color
uchar4 color;
setColor(color, colors, m, animationFrame);
setColor(color, colors, m, animationFrame);
// Output the pixel
updatePixel(dst[pixel], color, frame);
}
}
} // RunMandelbrotGold1_
// Output the pixel
updatePixel(dst[pixel], color, frame);
}
}
} // RunMandelbrotGold1_
/* Implementation of exported functions */
void RunMandelbrotGold1(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const float xOff, const float yOff,
const float xJParam, const float yJParam,
const float scale, const uchar4 colors, const int frame,
const int animationFrame, const bool isJulia) {
runMandelbrotGold1<float, float>(dst, imageW, imageH, crunch, xOff, yOff,
xJParam, yJParam, scale, colors, frame,
animationFrame, isJulia);
void RunMandelbrotGold1(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const float xOff,
const float yOff,
const float xJParam,
const float yJParam,
const float scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const bool isJulia)
{
runMandelbrotGold1<float, float>(
dst, imageW, imageH, crunch, xOff, yOff, xJParam, yJParam, scale, colors, frame, animationFrame, isJulia);
} // RunMandelbrotGold1
} // RunMandelbrotGold1
void RunMandelbrotDSGold1(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const double xOff,
const double yOff, const double xJParam,
const double yJParam, const double scale,
const uchar4 colors, const int frame,
const int animationFrame, const bool isJulia) {
runMandelbrotGold1<double, dfloat>(dst, imageW, imageH, crunch, xOff, yOff,
xJParam, yJParam, scale, colors, frame,
animationFrame, isJulia);
void RunMandelbrotDSGold1(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const double xOff,
const double yOff,
const double xJParam,
const double yJParam,
const double scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const bool isJulia)
{
runMandelbrotGold1<double, dfloat>(
dst, imageW, imageH, crunch, xOff, yOff, xJParam, yJParam, scale, colors, frame, animationFrame, isJulia);
} // RunMandelbrotDSGold1
} // RunMandelbrotDSGold1
void RunMandelbrotGold0(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const float xOff, const float yOff,
const float xJParam, const float yJParam,
const float scale, const uchar4 colors, const int frame,
const int animationFrame, const bool isJulia) {
runMandelbrotGold0<float, float>(dst, imageW, imageH, crunch, xOff, yOff,
xJParam, yJParam, scale, colors, frame,
animationFrame, isJulia);
} // RunMandelbrotGold0
void RunMandelbrotGold0(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const float xOff,
const float yOff,
const float xJParam,
const float yJParam,
const float scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const bool isJulia)
{
runMandelbrotGold0<float, float>(
dst, imageW, imageH, crunch, xOff, yOff, xJParam, yJParam, scale, colors, frame, animationFrame, isJulia);
} // RunMandelbrotGold0
void RunMandelbrotDSGold0(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const double xOff,
const double yOff, const double xJParam,
const double yJParam, const double scale,
const uchar4 colors, const int frame,
const int animationFrame, const bool isJulia) {
runMandelbrotGold0<double, dfloat>(dst, imageW, imageH, crunch, xOff, yOff,
xJParam, yJParam, scale, colors, frame,
animationFrame, isJulia);
} // RunMandelbrotDSGold0
void RunMandelbrotDSGold0(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const double xOff,
const double yOff,
const double xJParam,
const double yJParam,
const double scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const bool isJulia)
{
runMandelbrotGold0<double, dfloat>(
dst, imageW, imageH, crunch, xOff, yOff, xJParam, yJParam, scale, colors, frame, animationFrame, isJulia);
} // RunMandelbrotDSGold0
/*dfloat operations implementation */
/* Construct a DS number equal to a double precision floating point number b*/
dfloat::dfloat(double b) {
val[0] = (float)b;
val[1] = (float)(b - val[0]);
dfloat::dfloat(double b)
{
val[0] = (float)b;
val[1] = (float)(b - val[0]);
}
inline dfloat operator+(const dfloat &dsa, const dfloat &dsb) {
// Compute dsa + dsb using Knuth's trick.
float t1 = dsa[0] + dsb[0];
float e = t1 - dsa[0];
float t2 = ((dsb[0] - e) + (dsa[0] - (t1 - e))) + dsa[1] + dsb[1];
inline dfloat operator+(const dfloat &dsa, const dfloat &dsb)
{
// Compute dsa + dsb using Knuth's trick.
float t1 = dsa[0] + dsb[0];
float e = t1 - dsa[0];
float t2 = ((dsb[0] - e) + (dsa[0] - (t1 - e))) + dsa[1] + dsb[1];
// The result is t1 + t2, after normalization.
e = t1 + t2;
return dfloat(e, t2 - (e - t1));
// The result is t1 + t2, after normalization.
e = t1 + t2;
return dfloat(e, t2 - (e - t1));
}
inline dfloat operator-(const dfloat &dsa, const dfloat &dsb) {
// Compute dsa - dsb using Knuth's trick.
float t1 = dsa[0] - dsb[0];
float e = t1 - dsa[0];
float t2 = ((-dsb[0] - e) + (dsa[0] - (t1 - e))) + dsa[1] - dsb[1];
inline dfloat operator-(const dfloat &dsa, const dfloat &dsb)
{
// Compute dsa - dsb using Knuth's trick.
float t1 = dsa[0] - dsb[0];
float e = t1 - dsa[0];
float t2 = ((-dsb[0] - e) + (dsa[0] - (t1 - e))) + dsa[1] - dsb[1];
// The result is t1 + t2, after normalization.
e = t1 + t2;
return dfloat(e, t2 - (e - t1));
// The result is t1 + t2, after normalization.
e = t1 + t2;
return dfloat(e, t2 - (e - t1));
}
inline dfloat operator*(const dfloat &dsa, const dfloat &dsb) {
// This splits dsa(1) and dsb(1) into high-order and low-order words.
float c11 = dsa[0] * dsb[0];
float c21 = dsa[0] * dsb[0] - c11;
inline dfloat operator*(const dfloat &dsa, const dfloat &dsb)
{
// This splits dsa(1) and dsb(1) into high-order and low-order words.
float c11 = dsa[0] * dsb[0];
float c21 = dsa[0] * dsb[0] - c11;
// Compute dsa[0] * dsb[1] + dsa[1] * dsb[0] (only high-order word is needed).
float c2 = dsa[0] * dsb[1] + dsa[1] * dsb[0];
// Compute dsa[0] * dsb[1] + dsa[1] * dsb[0] (only high-order word is needed).
float c2 = dsa[0] * dsb[1] + dsa[1] * dsb[0];
// Compute (c11, c21) + c2 using Knuth's trick, also adding low-order product.
float t1 = c11 + c2;
float e = t1 - c11;
float t2 = ((c2 - e) + (c11 - (t1 - e))) + c21 + dsa[1] * dsb[1];
// Compute (c11, c21) + c2 using Knuth's trick, also adding low-order product.
float t1 = c11 + c2;
float e = t1 - c11;
float t2 = ((c2 - e) + (c11 - (t1 - e))) + c21 + dsa[1] * dsb[1];
// The result is t1 + t2, after normalization.
e = t1 + t2;
return dfloat(e, t2 - (e - t1));
// The result is t1 + t2, after normalization.
e = t1 + t2;
return dfloat(e, t2 - (e - t1));
}

View File

@@ -30,33 +30,57 @@
#include <vector_types.h>
extern "C" void RunMandelbrotGold0(uchar4 *dst, const int imageW,
const int imageH, const int crunch,
const float xOff, const float yOff,
const float xJParam, const float yJParam,
const float scale, const uchar4 colors,
const int frame, const int animationFrame,
const bool isJulia);
extern "C" void RunMandelbrotDSGold0(uchar4 *dst, const int imageW,
const int imageH, const int crunch,
const double xOff, const double yOff,
const double xJParam, const double yJParam,
const double scale, const uchar4 colors,
const int frame, const int animationFrame,
const bool isJulia);
extern "C" void RunMandelbrotGold1(uchar4 *dst, const int imageW,
const int imageH, const int crunch,
const float xOff, const float yOff,
const float xJParam, const float yJParam,
const float scale, const uchar4 colors,
const int frame, const int animationFrame,
const bool isJulia);
extern "C" void RunMandelbrotDSGold1(uchar4 *dst, const int imageW,
const int imageH, const int crunch,
const double xOff, const double yOff,
const double xJParam, const double yJParam,
const double scale, const uchar4 colors,
const int frame, const int animationFrame,
const bool isJulia);
extern "C" void RunMandelbrotGold0(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const float xOff,
const float yOff,
const float xJParam,
const float yJParam,
const float scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const bool isJulia);
extern "C" void RunMandelbrotDSGold0(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const double xOff,
const double yOff,
const double xJParam,
const double yJParam,
const double scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const bool isJulia);
extern "C" void RunMandelbrotGold1(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const float xOff,
const float yOff,
const float xJParam,
const float yJParam,
const float scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const bool isJulia);
extern "C" void RunMandelbrotDSGold1(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const double xOff,
const double yOff,
const double xJParam,
const double yJParam,
const double scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const bool isJulia);
#endif

View File

@@ -26,8 +26,9 @@
*/
#include <stdio.h>
#include "helper_cuda.h"
#include "Mandelbrot_kernel.h"
#include "helper_cuda.h"
// The dimensions of the thread block
#define BLOCKDIM_X 16
@@ -40,73 +41,75 @@
// This function sets the DS number A equal to the double precision floating
// point number B.
inline void dsdeq(float &a0, float &a1, double b) {
a0 = (float)b;
a1 = (float)(b - a0);
} // dsdcp
inline void dsdeq(float &a0, float &a1, double b)
{
a0 = (float)b;
a1 = (float)(b - a0);
} // dsdcp
// This function sets the DS number A equal to the single precision floating
// point number B.
__device__ inline void dsfeq(float &a0, float &a1, float b) {
a0 = b;
a1 = 0.0f;
} // dsfeq
__device__ inline void dsfeq(float &a0, float &a1, float b)
{
a0 = b;
a1 = 0.0f;
} // dsfeq
// This function computes c = a + b.
__device__ inline void dsadd(float &c0, float &c1, const float a0,
const float a1, const float b0, const float b1) {
// Compute dsa + dsb using Knuth's trick.
float t1 = a0 + b0;
float e = t1 - a0;
float t2 = ((b0 - e) + (a0 - (t1 - e))) + a1 + b1;
__device__ inline void dsadd(float &c0, float &c1, const float a0, const float a1, const float b0, const float b1)
{
// Compute dsa + dsb using Knuth's trick.
float t1 = a0 + b0;
float e = t1 - a0;
float t2 = ((b0 - e) + (a0 - (t1 - e))) + a1 + b1;
// The result is t1 + t2, after normalization.
c0 = e = t1 + t2;
c1 = t2 - (e - t1);
} // dsadd
// The result is t1 + t2, after normalization.
c0 = e = t1 + t2;
c1 = t2 - (e - t1);
} // dsadd
// This function computes c = a - b.
__device__ inline void dssub(float &c0, float &c1, const float a0,
const float a1, const float b0, const float b1) {
// Compute dsa - dsb using Knuth's trick.
float t1 = a0 - b0;
float e = t1 - a0;
float t2 = ((-b0 - e) + (a0 - (t1 - e))) + a1 - b1;
__device__ inline void dssub(float &c0, float &c1, const float a0, const float a1, const float b0, const float b1)
{
// Compute dsa - dsb using Knuth's trick.
float t1 = a0 - b0;
float e = t1 - a0;
float t2 = ((-b0 - e) + (a0 - (t1 - e))) + a1 - b1;
// The result is t1 + t2, after normalization.
c0 = e = t1 + t2;
c1 = t2 - (e - t1);
} // dssub
// The result is t1 + t2, after normalization.
c0 = e = t1 + t2;
c1 = t2 - (e - t1);
} // dssub
#if 1
// This function multiplies DS numbers A and B to yield the DS product C.
__device__ inline void dsmul(float &c0, float &c1, const float a0,
const float a1, const float b0, const float b1) {
// This splits dsa(1) and dsb(1) into high-order and low-order words.
float cona = a0 * 8193.0f;
float conb = b0 * 8193.0f;
float sa1 = cona - (cona - a0);
float sb1 = conb - (conb - b0);
float sa2 = a0 - sa1;
float sb2 = b0 - sb1;
__device__ inline void dsmul(float &c0, float &c1, const float a0, const float a1, const float b0, const float b1)
{
// This splits dsa(1) and dsb(1) into high-order and low-order words.
float cona = a0 * 8193.0f;
float conb = b0 * 8193.0f;
float sa1 = cona - (cona - a0);
float sb1 = conb - (conb - b0);
float sa2 = a0 - sa1;
float sb2 = b0 - sb1;
// Multilply a0 * b0 using Dekker's method.
float c11 = a0 * b0;
float c21 = (((sa1 * sb1 - c11) + sa1 * sb2) + sa2 * sb1) + sa2 * sb2;
// Multilply a0 * b0 using Dekker's method.
float c11 = a0 * b0;
float c21 = (((sa1 * sb1 - c11) + sa1 * sb2) + sa2 * sb1) + sa2 * sb2;
// Compute a0 * b1 + a1 * b0 (only high-order word is needed).
float c2 = a0 * b1 + a1 * b0;
// Compute a0 * b1 + a1 * b0 (only high-order word is needed).
float c2 = a0 * b1 + a1 * b0;
// Compute (c11, c21) + c2 using Knuth's trick, also adding low-order product.
float t1 = c11 + c2;
float e = t1 - c11;
float t2 = ((c2 - e) + (c11 - (t1 - e))) + c21 + a1 * b1;
// Compute (c11, c21) + c2 using Knuth's trick, also adding low-order product.
float t1 = c11 + c2;
float e = t1 - c11;
float t2 = ((c2 - e) + (c11 - (t1 - e))) + c21 + a1 * b1;
// The result is t1 + t2, after normalization.
c0 = e = t1 + t2;
c1 = t2 - (e - t1);
} // dsmul
// The result is t1 + t2, after normalization.
c0 = e = t1 + t2;
c1 = t2 - (e - t1);
} // dsmul
#else
@@ -118,32 +121,32 @@ __device__ inline void dsmul(float &c0, float &c1, const float a0,
*/
// This function multiplies DS numbers A and B to yield the DS product C.
__device__ inline void dsmul(float &c0, float &c1, const float a0,
const float a1, const float b0, const float b1) {
// This splits dsa(1) and dsb(1) into high-order and low-order words.
float cona = a0 * 8193.0f;
float conb = b0 * 8193.0f;
float sa1 = cona - (cona - a0);
float sb1 = conb - (conb - b0);
float sa2 = a0 - sa1;
float sb2 = b0 - sb1;
__device__ inline void dsmul(float &c0, float &c1, const float a0, const float a1, const float b0, const float b1)
{
// This splits dsa(1) and dsb(1) into high-order and low-order words.
float cona = a0 * 8193.0f;
float conb = b0 * 8193.0f;
float sa1 = cona - (cona - a0);
float sb1 = conb - (conb - b0);
float sa2 = a0 - sa1;
float sb2 = b0 - sb1;
// Multilply a0 * b0 using Dekker's method.
float c11 = __fmul_rn(a0, b0);
float c21 = (((sa1 * sb1 - c11) + sa1 * sb2) + sa2 * sb1) + sa2 * sb2;
// Multilply a0 * b0 using Dekker's method.
float c11 = __fmul_rn(a0, b0);
float c21 = (((sa1 * sb1 - c11) + sa1 * sb2) + sa2 * sb1) + sa2 * sb2;
// Compute a0 * b1 + a1 * b0 (only high-order word is needed).
float c2 = __fmul_rn(a0, b1) + __fmul_rn(a1, b0);
// Compute a0 * b1 + a1 * b0 (only high-order word is needed).
float c2 = __fmul_rn(a0, b1) + __fmul_rn(a1, b0);
// Compute (c11, c21) + c2 using Knuth's trick, also adding low-order product.
float t1 = c11 + c2;
float e = t1 - c11;
float t2 = ((c2 - e) + (c11 - (t1 - e))) + c21 + __fmul_rn(a1, b1);
// Compute (c11, c21) + c2 using Knuth's trick, also adding low-order product.
float t1 = c11 + c2;
float e = t1 - c11;
float t2 = ((c2 - e) + (c11 - (t1 - e))) + c21 + __fmul_rn(a1, b1);
// The result is t1 + t2, after normalization.
c0 = e = t1 + t2;
c1 = t2 - (e - t1);
} // dsmul
// The result is t1 + t2, after normalization.
c0 = e = t1 + t2;
c1 = t2 - (e - t1);
} // dsmul
#endif
@@ -151,306 +154,331 @@ __device__ inline void dsmul(float &c0, float &c1, const float a0,
#if 1
// Unrolled version
template <class T>
__device__ inline int CalcMandelbrot(const T xPos, const T yPos,
const T xJParam, const T yJParam,
const int crunch, const bool isJulia) {
T x, y, xx, yy;
int i = crunch;
__device__ inline int
CalcMandelbrot(const T xPos, const T yPos, const T xJParam, const T yJParam, const int crunch, const bool isJulia)
{
T x, y, xx, yy;
int i = crunch;
T xC, yC;
T xC, yC;
if (isJulia) {
xC = xJParam;
yC = yJParam;
y = yPos;
x = xPos;
yy = y * y;
xx = x * x;
if (isJulia) {
xC = xJParam;
yC = yJParam;
y = yPos;
x = xPos;
yy = y * y;
xx = x * x;
}
else {
xC = xPos;
yC = yPos;
y = 0;
x = 0;
yy = 0;
xx = 0;
}
} else {
xC = xPos;
yC = yPos;
y = 0;
x = 0;
yy = 0;
xx = 0;
}
do {
// Iteration 1
if (xx + yy > T(4.0))
return i - 1;
do {
// Iteration 1
if (xx + yy > T(4.0)) return i - 1;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 2
if (xx + yy > T(4.0))
return i - 2;
// Iteration 2
if (xx + yy > T(4.0)) return i - 2;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 3
if (xx + yy > T(4.0))
return i - 3;
// Iteration 3
if (xx + yy > T(4.0)) return i - 3;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 4
if (xx + yy > T(4.0))
return i - 4;
// Iteration 4
if (xx + yy > T(4.0)) return i - 4;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 5
if (xx + yy > T(4.0))
return i - 5;
// Iteration 5
if (xx + yy > T(4.0)) return i - 5;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 6
if (xx + yy > T(4.0))
return i - 6;
// Iteration 6
if (xx + yy > T(4.0)) return i - 6;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 7
if (xx + yy > T(4.0))
return i - 7;
// Iteration 7
if (xx + yy > T(4.0)) return i - 7;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 8
if (xx + yy > T(4.0))
return i - 8;
// Iteration 8
if (xx + yy > T(4.0)) return i - 8;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 9
if (xx + yy > T(4.0))
return i - 9;
// Iteration 9
if (xx + yy > T(4.0)) return i - 9;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 10
if (xx + yy > T(4.0))
return i - 10;
// Iteration 10
if (xx + yy > T(4.0)) return i - 10;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 11
if (xx + yy > T(4.0))
return i - 11;
// Iteration 11
if (xx + yy > T(4.0)) return i - 11;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 12
if (xx + yy > T(4.0))
return i - 12;
// Iteration 12
if (xx + yy > T(4.0)) return i - 12;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 13
if (xx + yy > T(4.0))
return i - 13;
// Iteration 13
if (xx + yy > T(4.0)) return i - 13;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 14
if (xx + yy > T(4.0))
return i - 14;
// Iteration 14
if (xx + yy > T(4.0)) return i - 14;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 15
if (xx + yy > T(4.0))
return i - 15;
// Iteration 15
if (xx + yy > T(4.0)) return i - 15;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 16
if (xx + yy > T(4.0))
return i - 16;
// Iteration 16
if (xx + yy > T(4.0)) return i - 16;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 17
if (xx + yy > T(4.0))
return i - 17;
// Iteration 17
if (xx + yy > T(4.0)) return i - 17;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 18
if (xx + yy > T(4.0))
return i - 18;
// Iteration 18
if (xx + yy > T(4.0)) return i - 18;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 19
if (xx + yy > T(4.0))
return i - 19;
// Iteration 19
if (xx + yy > T(4.0)) return i - 19;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
// Iteration 20
i -= 20;
// Iteration 20
i -= 20;
if ((i <= 0) || (xx + yy > T(4.0)))
return i;
if ((i <= 0) || (xx + yy > T(4.0))) return i;
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
} while (1);
} // CalcMandelbrot
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
} while (1);
} // CalcMandelbrot
#else
template <class T>
__device__ inline int CalcMandelbrot(const T xPos, const T yPos,
const T xJParam, const T yJParam,
const int crunch, const isJulia) {
T x, y, xx, yy, xC, yC;
__device__ inline int
CalcMandelbrot(const T xPos, const T yPos, const T xJParam, const T yJParam, const int crunch, const isJulia)
{
T x, y, xx, yy, xC, yC;
if (isJulia) {
xC = xJParam;
yC = yJParam;
y = yPos;
x = xPos;
yy = y * y;
xx = x * x;
if (isJulia) {
xC = xJParam;
yC = yJParam;
y = yPos;
x = xPos;
yy = y * y;
xx = x * x;
}
else {
xC = xPos;
yC = yPos;
y = 0;
x = 0;
yy = 0;
xx = 0;
}
} else {
xC = xPos;
yC = yPos;
y = 0;
x = 0;
yy = 0;
xx = 0;
}
int i = crunch;
int i = crunch;
while (--i && (xx + yy < T(4.0))) {
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
}
while (--i && (xx + yy < T(4.0))) {
y = x * y * T(2.0) + yC;
x = xx - yy + xC;
yy = y * y;
xx = x * x;
}
return i; // i > 0 ? crunch - i : 0;
} // CalcMandelbrot
return i; // i > 0 ? crunch - i : 0;
} // CalcMandelbrot
#endif
// The core Mandelbrot calculation function in double-single precision
__device__ inline int CalcMandelbrotDS(const float xPos0, const float xPos1,
const float yPos0, const float yPos1,
const float xJParam, const float yJParam,
const int crunch, const bool isJulia) {
float xx0, xx1;
float yy0, yy1;
float sum0, sum1;
int i = crunch;
__device__ inline int CalcMandelbrotDS(const float xPos0,
const float xPos1,
const float yPos0,
const float yPos1,
const float xJParam,
const float yJParam,
const int crunch,
const bool isJulia)
{
float xx0, xx1;
float yy0, yy1;
float sum0, sum1;
int i = crunch;
float x0, x1, y0, y1;
float xC0, xC1, yC0, yC1;
float x0, x1, y0, y1;
float xC0, xC1, yC0, yC1;
if (isJulia) {
xC0 = xJParam;
xC1 = 0;
yC0 = yJParam;
yC1 = 0;
y0 = yPos0; // y = yPos;
y1 = yPos1;
x0 = xPos0; // x = xPos;
x1 = xPos1;
dsmul(yy0, yy1, y0, y1, y0, y1); // yy = y * y;
dsmul(xx0, xx1, x0, x1, x0, x1); // xx = x * x;
} else {
xC0 = xPos0;
xC1 = xPos1;
yC0 = yPos0;
yC1 = yPos1;
y0 = 0; // y = 0 ;
y1 = 0;
x0 = 0; // x = 0 ;
x1 = 0;
yy0 = 0; // yy = 0 ;
yy1 = 0;
xx0 = 0; // xx = 0 ;
xx1 = 0;
}
if (isJulia) {
xC0 = xJParam;
xC1 = 0;
yC0 = yJParam;
yC1 = 0;
y0 = yPos0; // y = yPos;
y1 = yPos1;
x0 = xPos0; // x = xPos;
x1 = xPos1;
dsmul(yy0, yy1, y0, y1, y0, y1); // yy = y * y;
dsmul(xx0, xx1, x0, x1, x0, x1); // xx = x * x;
}
else {
xC0 = xPos0;
xC1 = xPos1;
yC0 = yPos0;
yC1 = yPos1;
y0 = 0; // y = 0 ;
y1 = 0;
x0 = 0; // x = 0 ;
x1 = 0;
yy0 = 0; // yy = 0 ;
yy1 = 0;
xx0 = 0; // xx = 0 ;
xx1 = 0;
}
dsadd(sum0, sum1, xx0, xx1, yy0, yy1); // sum = xx + yy;
dsadd(sum0, sum1, xx0, xx1, yy0, yy1); // sum = xx + yy;
while (--i && (sum0 + sum1 < 4.0f)) {
dsmul(y0, y1, x0, x1, y0, y1); // y = x * y * 2.0f + yC; // yC is yPos for
// Mandelbrot and it is yJParam for Julia
dsadd(y0, y1, y0, y1, y0, y1);
dsadd(y0, y1, y0, y1, yC0, yC1);
while (--i && (sum0 + sum1 < 4.0f)) {
dsmul(y0, y1, x0, x1, y0, y1); // y = x * y * 2.0f + yC; // yC is yPos for
// Mandelbrot and it is yJParam for Julia
dsadd(y0, y1, y0, y1, y0, y1);
dsadd(y0, y1, y0, y1, yC0, yC1);
dssub(x0, x1, xx0, xx1, yy0, yy1); // x = xx - yy + xC; // xC is xPos for
// Mandelbrot and it is xJParam for
// Julia
dsadd(x0, x1, x0, x1, xC0, xC1);
dssub(x0, x1, xx0, xx1, yy0, yy1); // x = xx - yy + xC; // xC is xPos for
// Mandelbrot and it is xJParam for
// Julia
dsadd(x0, x1, x0, x1, xC0, xC1);
dsmul(yy0, yy1, y0, y1, y0, y1); // yy = y * y;
dsmul(xx0, xx1, x0, x1, x0, x1); // xx = x * x;
dsadd(sum0, sum1, xx0, xx1, yy0, yy1); // sum = xx + yy;
}
dsmul(yy0, yy1, y0, y1, y0, y1); // yy = y * y;
dsmul(xx0, xx1, x0, x1, x0, x1); // xx = x * x;
dsadd(sum0, sum1, xx0, xx1, yy0, yy1); // sum = xx + yy;
}
return i;
} // CalcMandelbrotDS
return i;
} // CalcMandelbrotDS
// Determine if two pixel colors are within tolerance
__device__ inline int CheckColors(const uchar4 &color0, const uchar4 &color1) {
int x = color1.x - color0.x;
int y = color1.y - color0.y;
int z = color1.z - color0.z;
return (ABS(x) > 10) || (ABS(y) > 10) || (ABS(z) > 10);
} // CheckColors
__device__ inline int CheckColors(const uchar4 &color0, const uchar4 &color1)
{
int x = color1.x - color0.x;
int y = color1.y - color0.y;
int z = color1.z - color0.z;
return (ABS(x) > 10) || (ABS(y) > 10) || (ABS(z) > 10);
} // CheckColors
// Increase the grid size by 1 if the image width or height does not divide
// evenly
// by the thread block dimensions
inline int iDivUp(int a, int b) {
return ((a % b) != 0) ? (a / b + 1) : (a / b);
} // iDivUp
inline int iDivUp(int a, int b) { return ((a % b) != 0) ? (a / b + 1) : (a / b); } // iDivUp

View File

@@ -30,21 +30,37 @@
#include <vector_types.h>
extern "C" void RunMandelbrot0(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const double xOff,
const double yOff, const double xjp,
const double yjp, const double scale,
const uchar4 colors, const int frame,
const int animationFrame, const int mode,
const int numSMs, const bool isJ,
int version = 13);
extern "C" void RunMandelbrot1(uchar4 *dst, const int imageW, const int imageH,
const int crunch, const double xOff,
const double yOff, const double xjp,
const double yjp, const double scale,
const uchar4 colors, const int frame,
const int animationFrame, const int mode,
const int numSMs, const bool isJ,
int version = 13);
extern "C" void RunMandelbrot0(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const double xOff,
const double yOff,
const double xjp,
const double yjp,
const double scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const int mode,
const int numSMs,
const bool isJ,
int version = 13);
extern "C" void RunMandelbrot1(uchar4 *dst,
const int imageW,
const int imageH,
const int crunch,
const double xOff,
const double yOff,
const double xjp,
const double yjp,
const double scale,
const uchar4 colors,
const int frame,
const int animationFrame,
const int mode,
const int numSMs,
const bool isJ,
int version = 13);
#endif

View File

@@ -34,4 +34,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)