Index: MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/CMakeLists.txt =================================================================== --- MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/CMakeLists.txt +++ MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/CMakeLists.txt @@ -0,0 +1,12 @@ +set(IMAGEPROC_UTILS MicroBenchmarks/ImageProcessing/utils) + +list(APPEND CPPFLAGS -I ${CMAKE_SOURCE_DIR}/${IMAGEPROC_UTILS} -std=c++11) + +llvm_test_verify("${CMAKE_SOURCE_DIR}/HashProgramOutput.sh ${CMAKE_CURRENT_BINARY_DIR}/anisotropicDiffusionOutput.txt") +llvm_test_verify("${FPCMP} ${CMAKE_CURRENT_BINARY_DIR}/anisotropicDiffusionOutput.txt ${CMAKE_CURRENT_SOURCE_DIR}/anisotropicDiffusion.reference_output") + +llvm_test_run(WORKDIR ${CMAKE_CURRENT_BINARY_DIR}) + +llvm_test_executable(AnisotropicDiffusion ../utils/ImageHelper.cpp ../utils/glibc_compat_rand.c main.cpp anisotropicDiffusionKernel.c) + +target_link_libraries(AnisotropicDiffusion benchmark) Index: MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/anisotropicDiffusion.reference_output =================================================================== --- MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/anisotropicDiffusion.reference_output +++ MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/anisotropicDiffusion.reference_output @@ -0,0 +1 @@ +df287cfd3bd0d85a2bffd28b5bd37efd Index: MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/anisotropicDiffusionKernel.c =================================================================== --- MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/anisotropicDiffusionKernel.c +++ MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/anisotropicDiffusionKernel.c @@ -0,0 +1,55 @@ +/* + Source: + https://cboard.cprogramming.com/c-programming/164080-anisotropic-diffusion-implementation-c.html + Modified by Pankaj Kukreja (github.com/proton0001) + Indian Institute of Technology Hyderabad +*/ +#include "diffusion.h" +#include + +#define TIME_STEP 1.0 / 8 +#define DIFFUSION_CONST 0.5 +void anisotropicDiffusionKernel(int height, int width, + int inputImage[HEIGHT][WIDTH], + int outputImage[height][width], + int no_iteration) { + int i, j, k; + for (k = 0; k < no_iteration; k++) { + for (i = 2; i < height - 2; i++) { + for (j = 2; j < width - 2; j++) { + int gradient_x, gradient_y, grad_final; + float result; + float ne, nw, nn, ns; + gradient_x = inputImage[i][j + 2] - inputImage[i][j]; + gradient_y = inputImage[i + 1][j + 1] - inputImage[i - 1][j + 1]; + grad_final = gradient_x + gradient_y; + ne = exp(-(grad_final * grad_final) / DIFFUSION_CONST * + DIFFUSION_CONST) * + (inputImage[i][j + 1] - inputImage[i][j]); + + gradient_x = inputImage[i][j] - inputImage[i][j - 2]; + gradient_y = inputImage[i + 1][j - 1] - inputImage[i - 1][j - 1]; + grad_final = gradient_x + gradient_y; + nw = exp(-(grad_final * grad_final) / DIFFUSION_CONST * + DIFFUSION_CONST) * + (inputImage[i][j - 1] - inputImage[i][j]); + + gradient_x = inputImage[i - 1][j + 1] - inputImage[i - 1][j - 1]; + gradient_y = inputImage[i][j] - inputImage[i - 2][j]; + grad_final = gradient_x + gradient_y; + nn = exp(-(grad_final * grad_final) / DIFFUSION_CONST * + DIFFUSION_CONST) * + (inputImage[i - 1][j] - inputImage[i][j]); + + gradient_x = inputImage[i + 1][j + 1] - inputImage[i + 1][j - 1]; + gradient_y = inputImage[i + 2][j] - inputImage[i][j]; + grad_final = gradient_x + gradient_y; + ns = exp(-(grad_final * grad_final) / DIFFUSION_CONST * + DIFFUSION_CONST) * + (inputImage[i + 1][j] - inputImage[i][j]); + + outputImage[i][j] = inputImage[i][j] + TIME_STEP * (ne + nw + nn + ns); + } + } + } +} Index: MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/diffusion.h =================================================================== --- MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/diffusion.h +++ MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/diffusion.h @@ -0,0 +1,14 @@ +/** + Pankaj Kukreja + github.com/proton0001 + Indian Institute of Technology Hyderabad +*/ +#ifndef _DIFFUSSION_H +#define _DIFFUSSION_H + +#define HEIGHT 512 +#define WIDTH 512 + +#define ITERATION 10 + +#endif /* _DIFFUSSION_H */ Index: MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/main.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/main.cpp +++ MicroBenchmarks/ImageProcessing/AnisotropicDiffusion/main.cpp @@ -0,0 +1,108 @@ +/** + Pankaj Kukreja + github.com/proton0001 + Indian Institute of Technology Hyderabad +*/ + +#include "ImageHelper.h" +#include "diffusion.h" +#include // std::cerr + +#define BENCHMARK_LIB +#ifdef BENCHMARK_LIB +#include "benchmark/benchmark.h" +#endif + +int *inputImage; +extern "C" void anisotropicDiffusionKernel(int height, int width, int *source, + int *destination, int num_iteration); +int main(int argc, char *argv[]) { + +#ifdef BENCHMARK_LIB + ::benchmark::Initialize(&argc, argv); +#endif + + const char *anisotropicDiffusionOutputFileName = + (const char *)"./anisotropicDiffusionOutput.txt"; + + inputImage = (int *)malloc(sizeof(int) * (HEIGHT) * (WIDTH)); + + if (inputImage == NULL) { + std::cerr << "Insufficient memory\n"; + exit(EXIT_FAILURE); + } + + initializeRandomImage(inputImage, HEIGHT, WIDTH); + +#ifdef BENCHMARK_LIB + ::benchmark::RunSpecifiedBenchmarks(); +#endif + + int *outputImage; + outputImage = (int *)malloc(sizeof(int) * (HEIGHT) * (WIDTH)); + if (outputImage == NULL) { + std::cerr << "Insufficient memory\n"; + exit(EXIT_FAILURE); + } + + anisotropicDiffusionKernel(HEIGHT, WIDTH, inputImage, outputImage, ITERATION); + + for (int j = 0; j < WIDTH; j++) { + outputImage[0 + j] = 0; + outputImage[1 * WIDTH + j] = 0; + outputImage[(HEIGHT - 1) * WIDTH + j] = 0; + outputImage[(HEIGHT - 2) * WIDTH + j] = 0; + } + + for (int i = 0; i < HEIGHT; i++) { + outputImage[i * WIDTH + 0] = 0; + outputImage[i * WIDTH + 1] = 0; + outputImage[i * WIDTH + (WIDTH - 1)] = 0; + outputImage[i * WIDTH + (WIDTH - 2)] = 0; + } + + saveImage(outputImage, anisotropicDiffusionOutputFileName, HEIGHT, WIDTH); + + free(outputImage); + free(inputImage); + + return EXIT_SUCCESS; +} + +#ifdef BENCHMARK_LIB +void BENCHMARK_ANISTROPIC_DIFFUSION(benchmark::State &state) { + + int height = state.range(0); + int width = state.range(0); + + int *outputImage; + outputImage = (int *)malloc(sizeof(int) * (height) * (width)); + if (outputImage == NULL) { + std::cerr << "Insufficient memory\n"; + exit(EXIT_FAILURE); + } + /* first call made to warm up cache */ + anisotropicDiffusionKernel(height, width, inputImage, outputImage, ITERATION); + + for (auto _ : state) { + anisotropicDiffusionKernel(height, width, inputImage, outputImage, + ITERATION); + } + /* Since we are not passing state.range as 20 this if case will always be + * false. + * This call is to make compiler think that outputImage may be used + * later so that above kernel calls will not get optimize out */ + if (state.range(0) == 20) { + saveImage(outputImage, (const char *)"testFailed.txt", height, width); + } + + free(outputImage); +} + +BENCHMARK(BENCHMARK_ANISTROPIC_DIFFUSION) + ->Arg(32) + ->Arg(64) + ->Arg(128) + ->Arg(256) + ->Unit(benchmark::kMicrosecond); +#endif Index: MicroBenchmarks/ImageProcessing/CMakeLists.txt =================================================================== --- MicroBenchmarks/ImageProcessing/CMakeLists.txt +++ MicroBenchmarks/ImageProcessing/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(AnisotropicDiffusion)