aboutsummaryrefslogtreecommitdiff
path: root/MicroBenchmarks
diff options
context:
space:
mode:
authorPankaj Kukreja <cs15btech11029@iith.ac.in>2018-08-06 21:16:07 +0000
committerPankaj Kukreja <cs15btech11029@iith.ac.in>2018-08-06 21:16:07 +0000
commit4c6c9b86d177819151fe50334988308525e08041 (patch)
treec654125db1346a85a47bb5b144fb3a24c46c3c4d /MicroBenchmarks
parent8f9cb4a57f469269ede64f8e8e29be96f710ad52 (diff)
Add image blur algorithms using Benchmark Library
Contains Implementation of mean box blur and gaussian blur Reviewers: Meinersbur Differential Revision: https://reviews.llvm.org/D49341 git-svn-id: https://llvm.org/svn/llvm-project/test-suite/trunk@339055 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'MicroBenchmarks')
-rw-r--r--MicroBenchmarks/ImageProcessing/Blur/CMakeLists.txt15
-rw-r--r--MicroBenchmarks/ImageProcessing/Blur/blur.h15
-rw-r--r--MicroBenchmarks/ImageProcessing/Blur/boxBlur.reference_output1
-rw-r--r--MicroBenchmarks/ImageProcessing/Blur/boxBlurKernel.c26
-rw-r--r--MicroBenchmarks/ImageProcessing/Blur/gaussianBlur.reference_output1
-rw-r--r--MicroBenchmarks/ImageProcessing/Blur/gaussianBlurKernel.c45
-rw-r--r--MicroBenchmarks/ImageProcessing/Blur/main.cpp192
-rw-r--r--MicroBenchmarks/ImageProcessing/CMakeLists.txt1
8 files changed, 296 insertions, 0 deletions
diff --git a/MicroBenchmarks/ImageProcessing/Blur/CMakeLists.txt b/MicroBenchmarks/ImageProcessing/Blur/CMakeLists.txt
new file mode 100644
index 00000000..551e6ed6
--- /dev/null
+++ b/MicroBenchmarks/ImageProcessing/Blur/CMakeLists.txt
@@ -0,0 +1,15 @@
+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}/boxBlurOutput.txt")
+llvm_test_verify("${FPCMP} ${CMAKE_CURRENT_BINARY_DIR}/boxBlurOutput.txt ${CMAKE_CURRENT_SOURCE_DIR}/boxBlur.reference_output")
+
+llvm_test_verify("${CMAKE_SOURCE_DIR}/HashProgramOutput.sh ${CMAKE_CURRENT_BINARY_DIR}/gaussianBlurOutput.txt")
+llvm_test_verify("${FPCMP} ${CMAKE_CURRENT_BINARY_DIR}/gaussianBlurOutput.txt ${CMAKE_CURRENT_SOURCE_DIR}/gaussianBlur.reference_output")
+
+llvm_test_run(WORKDIR ${CMAKE_CURRENT_BINARY_DIR})
+
+llvm_test_executable(blur ../utils/ImageHelper.cpp ../utils/glibc_compat_rand.c main.cpp boxBlurKernel.c gaussianBlurKernel.c)
+
+target_link_libraries(blur benchmark)
diff --git a/MicroBenchmarks/ImageProcessing/Blur/blur.h b/MicroBenchmarks/ImageProcessing/Blur/blur.h
new file mode 100644
index 00000000..403f5a0a
--- /dev/null
+++ b/MicroBenchmarks/ImageProcessing/Blur/blur.h
@@ -0,0 +1,15 @@
+/**
+Pankaj Kukreja
+github.com/proton0001
+Indian Institute of Technology Hyderabad
+*/
+
+#ifndef _BOX_BLUR_H
+#define _BOX_BLUR_H
+
+#define HEIGHT 1024
+#define WIDTH 1024
+
+#define BOX_SIZE 9
+
+#endif /* _BOX_BLUR_H */
diff --git a/MicroBenchmarks/ImageProcessing/Blur/boxBlur.reference_output b/MicroBenchmarks/ImageProcessing/Blur/boxBlur.reference_output
new file mode 100644
index 00000000..d128b2f0
--- /dev/null
+++ b/MicroBenchmarks/ImageProcessing/Blur/boxBlur.reference_output
@@ -0,0 +1 @@
+d976614a6d0487da6873eb9de4044480
diff --git a/MicroBenchmarks/ImageProcessing/Blur/boxBlurKernel.c b/MicroBenchmarks/ImageProcessing/Blur/boxBlurKernel.c
new file mode 100644
index 00000000..5bc01b34
--- /dev/null
+++ b/MicroBenchmarks/ImageProcessing/Blur/boxBlurKernel.c
@@ -0,0 +1,26 @@
+/**
+Blur an Image using box blur
+
+Pankaj Kukreja
+Indian Institute of Technology Hyderabad
+*/
+
+#include "blur.h"
+void boxBlurKernel(int height, int width, int inputImage[HEIGHT][WIDTH],
+ int outputImage[height][width]) {
+ int sum = 0;
+ int offset = (BOX_SIZE - 1) / 2;
+ int n = BOX_SIZE * BOX_SIZE;
+
+ for (int i = offset; i < height - offset; i++) {
+ for (int j = offset; j < width - offset; j++) {
+ sum = 0;
+ for (int k = -1 * offset; k < offset; k++) {
+ for (int l = -1 * offset; l < offset; l++) {
+ sum += inputImage[i + k][j + l];
+ }
+ }
+ outputImage[i][j] = (sum) / (n);
+ }
+ }
+} \ No newline at end of file
diff --git a/MicroBenchmarks/ImageProcessing/Blur/gaussianBlur.reference_output b/MicroBenchmarks/ImageProcessing/Blur/gaussianBlur.reference_output
new file mode 100644
index 00000000..79e1a8ef
--- /dev/null
+++ b/MicroBenchmarks/ImageProcessing/Blur/gaussianBlur.reference_output
@@ -0,0 +1 @@
+7f4246596bcfbb5e6e44cd21ddfeaf07
diff --git a/MicroBenchmarks/ImageProcessing/Blur/gaussianBlurKernel.c b/MicroBenchmarks/ImageProcessing/Blur/gaussianBlurKernel.c
new file mode 100644
index 00000000..513732fb
--- /dev/null
+++ b/MicroBenchmarks/ImageProcessing/Blur/gaussianBlurKernel.c
@@ -0,0 +1,45 @@
+/**
+Gaussian Blur Kernel
+
+Pankaj Kukreja
+github.com/proton0001
+Indian Institute of Technology Hyderabad
+*/
+
+#include "blur.h"
+#include <math.h> // For M_PI and exp
+
+void gaussianBlurKernel(int height, int width, int inputImage[height][width],
+ int outputImage[height][width]) {
+
+ float sigma = 9;
+ float s = 2.0 * sigma * sigma;
+ int offset = (BOX_SIZE - 1) / 2;
+
+ float sum = 0;
+ float gaussianFilter[BOX_SIZE][BOX_SIZE] = {0};
+
+ for (int x = -1 * offset; x <= offset; x++) {
+ for (int y = -1 * offset; y <= offset; y++) {
+ gaussianFilter[x + offset][y + offset] =
+ (exp(-(x * x + y * y) / s)) / (M_PI * s);
+ sum += gaussianFilter[x + offset][y + offset];
+ }
+ }
+
+ float sum_in_current_frame = 0;
+ for (int i = offset; i < height - offset; i++) {
+ for (int j = offset; j < width - offset; j++) {
+ /* Computing sum of (elements * corresponding gaussianFilter) in window
+ * centered at i,j */
+ sum_in_current_frame = 0;
+ for (int k = -1 * offset; k <= offset; k++) {
+ for (int l = -1 * offset; l <= offset; l++) {
+ sum_in_current_frame += (inputImage[i + k][j + l] *
+ gaussianFilter[k + offset][l + offset]);
+ }
+ }
+ outputImage[i][j] = (sum_in_current_frame) / sum;
+ }
+ }
+}
diff --git a/MicroBenchmarks/ImageProcessing/Blur/main.cpp b/MicroBenchmarks/ImageProcessing/Blur/main.cpp
new file mode 100644
index 00000000..9d35c21a
--- /dev/null
+++ b/MicroBenchmarks/ImageProcessing/Blur/main.cpp
@@ -0,0 +1,192 @@
+/**
+Pankaj Kukreja
+github.com/proton0001
+Indian Institute of Technology Hyderabad
+*/
+
+#include "ImageHelper.h"
+#include "blur.h"
+#include <iostream>
+
+#define BENCHMARK_LIB
+#ifdef BENCHMARK_LIB
+#include "benchmark/benchmark.h"
+#endif
+extern "C" void boxBlurKernel(int height, int width, int *inpImage,
+ int *outpImage);
+extern "C" void gaussianBlurKernel(int height, int width, int *inpImage,
+ int *outpImage);
+int *inputImage;
+int main(int argc, char *argv[]) {
+
+#ifdef BENCHMARK_LIB
+ ::benchmark::Initialize(&argc, argv);
+#endif
+
+ const char *boxBlurOutputFileName = (const char *)"./boxBlurOutput.txt";
+ const char *gaussianBlurOutputFileName =
+ (const char *)"./gaussianBlurOutput.txt";
+
+ inputImage = (int *)malloc(sizeof(int) * (HEIGHT) * (WIDTH));
+
+ if (inputImage == NULL) {
+ std::cerr << "Insufficient memory\n";
+ exit(1);
+ }
+
+ initializeRandomImage(inputImage, HEIGHT, WIDTH);
+
+// Run Kernels Using Benchmark Library
+#ifdef BENCHMARK_LIB
+ ::benchmark::RunSpecifiedBenchmarks();
+#endif
+
+ // Run Kernels once more and save output in a file for Verification
+ int *outputImage;
+ outputImage = (int *)malloc(sizeof(int) * (HEIGHT) * (WIDTH));
+
+ if (outputImage == NULL) {
+ std::cerr << "Insufficient memory\n";
+ exit(1);
+ }
+
+ boxBlurKernel(HEIGHT, WIDTH, inputImage, outputImage);
+
+ // Blur not applied on edges so we add a black border
+ // Otherwise we may get garbage value which may create problem in output
+ // verification
+
+ int offset = (BOX_SIZE - 1) / 2;
+ // Top Edge
+ for (int i = 0; i < offset; i++) {
+ for (int j = 0; j < WIDTH; j++) {
+ outputImage[i * WIDTH + j] = 0;
+ }
+ }
+
+ // Bottom Edge
+ for (int i = HEIGHT - offset; i < HEIGHT; i++) {
+ for (int j = 0; j < WIDTH; j++) {
+ outputImage[i * WIDTH + j] = 0;
+ }
+ }
+
+ // Left Edge
+ for (int i = 0; i < HEIGHT; i++) {
+ for (int j = 0; j < offset; j++) {
+ outputImage[i * WIDTH + j] = 0;
+ }
+ }
+ // Right Edge
+ for (int i = 0; i < HEIGHT; i++) {
+ for (int j = WIDTH - offset; j < WIDTH; j++) {
+ outputImage[i * WIDTH + j] = 0;
+ }
+ }
+
+ saveImage(outputImage, boxBlurOutputFileName, HEIGHT, WIDTH);
+
+ gaussianBlurKernel(HEIGHT, WIDTH, inputImage, outputImage);
+
+ // Top Edge
+ for (int i = 0; i < offset; i++) {
+ for (int j = 0; j < WIDTH; j++) {
+ outputImage[i * WIDTH + j] = 0;
+ }
+ }
+
+ // Bottom Edge
+ for (int i = HEIGHT - offset; i < HEIGHT; i++) {
+ for (int j = 0; j < WIDTH; j++) {
+ outputImage[i * WIDTH + j] = 0;
+ }
+ }
+
+ // Left Edge
+ for (int i = 0; i < HEIGHT; i++) {
+ for (int j = 0; j < offset; j++) {
+ outputImage[i * WIDTH + j] = 0;
+ }
+ }
+ // Right Edge
+ for (int i = 0; i < HEIGHT; i++) {
+ for (int j = WIDTH - offset; j < WIDTH; j++) {
+ outputImage[i * WIDTH + j] = 0;
+ }
+ }
+
+ saveImage(outputImage, gaussianBlurOutputFileName, HEIGHT, WIDTH);
+
+ free(outputImage);
+ free(inputImage);
+ return EXIT_SUCCESS;
+}
+
+#ifdef BENCHMARK_LIB
+void BENCHMARK_boxBlurKernel(benchmark::State &state) {
+
+ int height = state.range(0);
+ int width = state.range(1);
+
+ int *outputImage = (int *)malloc(sizeof(int) * (height) * (width));
+
+ if (outputImage == NULL) {
+ std::cerr << "Insufficient memory\n";
+ exit(1);
+ }
+ /* This call is to warm up the cache */
+ boxBlurKernel(height, width, inputImage, outputImage);
+
+ for (auto _ : state) {
+ boxBlurKernel(height, width, inputImage, outputImage);
+ }
+ /* Since we are not passing state.range as 20 this if case will always be
+ * false. This if case is to prevent above kernel calls from getting optimized
+ * out */
+ if (state.range(0) == 20) {
+ saveImage(outputImage, (const char *)"testFailed.txt", height, width);
+ }
+
+ free(outputImage);
+}
+BENCHMARK(BENCHMARK_boxBlurKernel)
+ ->Args({128, 128})
+ ->Args({256, 256})
+ ->Args({512, 512})
+ ->Args({1024, 1024})
+ ->Unit(benchmark::kMicrosecond);
+
+void BENCHMARK_GAUSSIAN_BLUR(benchmark::State &state) {
+
+ int height = state.range(0);
+ int width = state.range(1);
+
+ int *outputImage = (int *)malloc(sizeof(int) * (height) * (width));
+
+ if (outputImage == NULL) {
+ std::cerr << "Insufficient memory\n";
+ exit(1);
+ }
+ /* This call is to warm up the cache */
+ gaussianBlurKernel(height, width, inputImage, outputImage);
+
+ for (auto _ : state) {
+ gaussianBlurKernel(height, width, inputImage, outputImage);
+ }
+ /* Since we are not passing state.range as 20 this if case will always be
+ * false. This if case is to prevent above kernel calls from getting optimized
+ * out */
+ if (state.range(0) == 20) {
+ saveImage(outputImage, (const char *)"testFailed.txt", height, width);
+ }
+
+ free(outputImage);
+}
+
+BENCHMARK(BENCHMARK_GAUSSIAN_BLUR)
+ ->Args({128, 128})
+ ->Args({256, 256})
+ ->Args({512, 512})
+ ->Args({1024, 1024})
+ ->Unit(benchmark::kMicrosecond);
+#endif
diff --git a/MicroBenchmarks/ImageProcessing/CMakeLists.txt b/MicroBenchmarks/ImageProcessing/CMakeLists.txt
index 666dce49..eb808f12 100644
--- a/MicroBenchmarks/ImageProcessing/CMakeLists.txt
+++ b/MicroBenchmarks/ImageProcessing/CMakeLists.txt
@@ -1,2 +1,3 @@
add_subdirectory(Dither)
add_subdirectory(AnisotropicDiffusion)
+add_subdirectory(Blur)