From 4f78d5110e5d6b0c69737e03dd247356ba4a8677 Mon Sep 17 00:00:00 2001 From: meshtag <prathameshtagore@gmail.com> Date: Wed, 8 Sep 2021 00:16:37 +0530 Subject: [PATCH] Add opencv benchmark Edit Doc Edit readme and comments Refactor code Use benchmark arhuments to reduce repetitiveness Change file structure Add comments in Benchmarks folder and update README.md with compilation instruction --- README.md | 4 +- .../Benchmarks/BenchmarkFiles/CMakeLists.txt | 1 + .../ImageProcessing/BuddyBenchmark.cpp | 82 ++++++++++++++ .../ImageProcessing/CMakeLists.txt | 47 ++++++++ .../ImageProcessing/CompareBuddyOpencv.cpp | 100 ++++++++++++++++++ .../ImageProcessing/OpenCVBenchmark.cpp | 36 +++++++ buddy-mlir/Benchmarks/CMakeLists.txt | 1 + .../ImageProcessing/BuddyContainer.hpp | 39 +++++++ 8 files changed, 309 insertions(+), 1 deletion(-) create mode 100644 buddy-mlir/Benchmarks/BenchmarkFiles/CMakeLists.txt create mode 100644 buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/BuddyBenchmark.cpp create mode 100644 buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/CMakeLists.txt create mode 100644 buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/CompareBuddyOpencv.cpp create mode 100644 buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/OpenCVBenchmark.cpp create mode 100644 buddy-mlir/Benchmarks/CMakeLists.txt create mode 100644 buddy-mlir/Benchmarks/include/ImageProcessing/BuddyContainer.hpp diff --git a/README.md b/README.md index bc03ddc..1b81ccf 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # buddy-benchmark -Benchmark Framework for Buddy Projects +In order to produce benchmarking results, copy and paste the `benchmarks` folder in `examples/conv-opt/` directory. Also add `add_subdirectory(Benchmarks)` in `examples/conv-opt/CMakeLists.txt`. + +Note : The convolution implementation in buddy mlir is not feature complete at the moment and it may produce output which differs to some extent from the frameworks used in comparison. diff --git a/buddy-mlir/Benchmarks/BenchmarkFiles/CMakeLists.txt b/buddy-mlir/Benchmarks/BenchmarkFiles/CMakeLists.txt new file mode 100644 index 0000000..6071631 --- /dev/null +++ b/buddy-mlir/Benchmarks/BenchmarkFiles/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(ImageProcessing) diff --git a/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/BuddyBenchmark.cpp b/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/BuddyBenchmark.cpp new file mode 100644 index 0000000..b98cabd --- /dev/null +++ b/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/BuddyBenchmark.cpp @@ -0,0 +1,82 @@ +#include <benchmark/benchmark.h> +#include <opencv2/opencv.hpp> +#include "../../../kernels.h" +#include "../../include/ImageProcessing/BuddyContainer.hpp" + +using namespace cv; +using namespace std; + +// Read input image +Mat inputImage = imread("../../examples/conv-opt/images/YuTu.png", IMREAD_GRAYSCALE); + +// Define the kernel. +float *kernelAlign = laplacianKernelAlign; +int kernelRows = laplacianKernelRows; +int kernelCols = laplacianKernelCols; + +// Define output for buddy mlir implementation. +int outputRows = inputImage.rows - kernelRows + 1; +int outputCols = inputImage.cols - kernelCols + 1; +float *outputAlign = (float *)malloc(outputRows * outputCols * sizeof(float)); + +// Define allocated, sizes, and strides. +float *allocated = (float *)malloc(1 * sizeof(float)); +intptr_t sizesInput[2] = {inputImage.rows, inputImage.cols}; +intptr_t sizesKernel[2] = {kernelRows, kernelCols}; +intptr_t sizesOutput[2] = {outputRows, outputCols}; +intptr_t stridesInput[2] = {inputImage.rows, inputImage.cols}; +intptr_t stridesKernel[2] = {kernelRows, kernelCols}; +intptr_t stridesOutput[2] = {outputRows, outputCols}; + +float* fill_align(Mat image) +{ + int k = 0; + float *inputAlign = (float *)malloc(image.rows * image.cols * sizeof(float)); + for (int i = 0; i < image.rows; i++) { + for (int j = 0; j < image.cols; j++) { + float pixelValue = (float)image.at<uchar>(i, j); + inputAlign[k] = pixelValue; + k++; + } + } + return inputAlign; +} + +float *inputAlign = fill_align(inputImage); + +// Define memref descriptors. +MemRef_descriptor input = + MemRef_Descriptor(allocated, inputAlign, 0, sizesInput, stridesInput); +MemRef_descriptor kernel = + MemRef_Descriptor(allocated, kernelAlign, 0, sizesKernel, stridesKernel); +MemRef_descriptor output = + MemRef_Descriptor(allocated, outputAlign, 0, sizesOutput, stridesOutput); + +static void BM_Buddy(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + _mlir_ciface_conv_2d(input, kernel, output); + } + } +} + +// Register benchmarking function with different arguments +BENCHMARK(BM_Buddy)->Arg(1); +BENCHMARK(BM_Buddy)->Arg(2); +BENCHMARK(BM_Buddy)->Arg(4); +BENCHMARK(BM_Buddy)->Arg(8); +BENCHMARK(BM_Buddy)->Arg(16); + +// Run benchmarks +int main(int argc, char** argv) +{ + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + + free(inputAlign); + free(outputAlign); + free(input); + free(kernel); + free(output); + free(allocated); +} diff --git a/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/CMakeLists.txt b/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/CMakeLists.txt new file mode 100644 index 0000000..032f255 --- /dev/null +++ b/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/CMakeLists.txt @@ -0,0 +1,47 @@ +find_package(OpenCV REQUIRED CONFIG) +include_directories(${OpenCV_INCLUDE_DIRS}) + +message(STATUS "Configuring benchmarks: google") + +#----------------------------------------------------------------------------- +# Deploy google/benchmark +#----------------------------------------------------------------------------- +include(ExternalProject) + +ExternalProject_Add(project_googlebenchmark + GIT_REPOSITORY https://github.com/google/benchmark.git + GIT_TAG "v1.6.0" + GIT_SHALLOW 1 + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/benchmark + TIMEOUT 10 + BUILD_BYPRODUCTS <INSTALL_DIR>/lib/${CMAKE_STATIC_LIBRARY_PREFIX}benchmark${CMAKE_STATIC_LIBRARY_SUFFIX} + CMAKE_ARGS + -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/vendor/benchmark + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DBENCHMARK_ENABLE_TESTING=OFF + UPDATE_COMMAND "" + TEST_COMMAND "") + +ExternalProject_Get_Property(project_googlebenchmark INSTALL_DIR) + +file(MAKE_DIRECTORY ${INSTALL_DIR}/include) +add_library(buddy_googlebenchmark STATIC IMPORTED) +target_include_directories(buddy_googlebenchmark INTERFACE ${INSTALL_DIR}/include) +set_property(TARGET buddy_googlebenchmark PROPERTY IMPORTED_LOCATION + "${INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}benchmark${CMAKE_STATIC_LIBRARY_SUFFIX}") + +add_dependencies(buddy_googlebenchmark project_googlebenchmark) + +find_package(Threads) +target_link_libraries(buddy_googlebenchmark INTERFACE Threads::Threads) + +add_executable(OpenCVBenchmark OpenCVBenchmark.cpp) +target_link_libraries(OpenCVBenchmark ${OpenCV_LIBS} buddy_googlebenchmark) + +add_executable(BuddyBenchmark BuddyBenchmark.cpp) +add_dependencies(BuddyBenchmark conv-opt) +target_link_libraries(BuddyBenchmark ${OpenCV_LIBS} Conv2D buddy_googlebenchmark) + +add_executable(CompareBuddyOpencv CompareBuddyOpencv.cpp) +add_dependencies(CompareBuddyOpencv conv-opt) +target_link_libraries(CompareBuddyOpencv ${OpenCV_LIBS} Conv2D buddy_googlebenchmark) diff --git a/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/CompareBuddyOpencv.cpp b/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/CompareBuddyOpencv.cpp new file mode 100644 index 0000000..a3b565d --- /dev/null +++ b/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/CompareBuddyOpencv.cpp @@ -0,0 +1,100 @@ +#include <benchmark/benchmark.h> +#include <opencv2/opencv.hpp> +#include "../../../kernels.h" +#include "../../include/ImageProcessing/BuddyContainer.hpp" + +using namespace cv; +using namespace std; + +// Read input image and specify kernel +Mat inputImage = imread("../../examples/conv-opt/images/YuTu.png", IMREAD_GRAYSCALE); +Mat kernel_opencv = Mat(3, 3, CV_32FC1, laplacianKernelAlign); +Mat output_opencv; + +// Define the kernel. +float *kernelAlign = laplacianKernelAlign; +int kernelRows = laplacianKernelRows; +int kernelCols = laplacianKernelCols; + +// Define output for buddy mlir implementation. +int outputRows = inputImage.rows - kernelRows + 1; +int outputCols = inputImage.cols - kernelCols + 1; +float *outputAlign = (float *)malloc(outputRows * outputCols * sizeof(float)); + +// Define allocated, sizes, and strides. +float *allocated = (float *)malloc(1 * sizeof(float)); +intptr_t sizesInput[2] = {inputImage.rows, inputImage.cols}; +intptr_t sizesKernel[2] = {kernelRows, kernelCols}; +intptr_t sizesOutput[2] = {outputRows, outputCols}; +intptr_t stridesInput[2] = {inputImage.rows, inputImage.cols}; +intptr_t stridesKernel[2] = {kernelRows, kernelCols}; +intptr_t stridesOutput[2] = {outputRows, outputCols}; + +float* fill_align(Mat image) +{ + int k = 0; + float *inputAlign = (float *)malloc(image.rows * image.cols * sizeof(float)); + for (int i = 0; i < image.rows; i++) { + for (int j = 0; j < image.cols; j++) { + float pixelValue = (float)image.at<uchar>(i, j); + inputAlign[k] = pixelValue; + k++; + } + } + return inputAlign; +} + +float *inputAlign = fill_align(inputImage); + +// Define memref descriptors. +MemRef_descriptor input = + MemRef_Descriptor(allocated, inputAlign, 0, sizesInput, stridesInput); +MemRef_descriptor kernel = + MemRef_Descriptor(allocated, kernelAlign, 0, sizesKernel, stridesKernel); +MemRef_descriptor output = + MemRef_Descriptor(allocated, outputAlign, 0, sizesOutput, stridesOutput); + +// Benchmarking function +static void BM_OpenCV(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + filter2D(inputImage, output_opencv, CV_32FC1, kernel_opencv); + } + } +} + +// Benchmarking function +static void BM_Buddy(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + _mlir_ciface_conv_2d(input, kernel, output); + } + } +} + +// Register above functions as benchmarks with different arguments +BENCHMARK(BM_OpenCV)->Arg(1); +BENCHMARK(BM_OpenCV)->Arg(2); +BENCHMARK(BM_OpenCV)->Arg(4); +BENCHMARK(BM_OpenCV)->Arg(8); +BENCHMARK(BM_OpenCV)->Arg(16); + +BENCHMARK(BM_Buddy)->Arg(1); +BENCHMARK(BM_Buddy)->Arg(2); +BENCHMARK(BM_Buddy)->Arg(4); +BENCHMARK(BM_Buddy)->Arg(8); +BENCHMARK(BM_Buddy)->Arg(16); + +// Run benchmarks +int main(int argc, char** argv) +{ + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + + free(inputAlign); + free(outputAlign); + free(input); + free(kernel); + free(output); + free(allocated); +} diff --git a/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/OpenCVBenchmark.cpp b/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/OpenCVBenchmark.cpp new file mode 100644 index 0000000..188bfa6 --- /dev/null +++ b/buddy-mlir/Benchmarks/BenchmarkFiles/ImageProcessing/OpenCVBenchmark.cpp @@ -0,0 +1,36 @@ +#include <benchmark/benchmark.h> +#include <opencv2/opencv.hpp> +#include "../../../kernels.h" + +using namespace cv; +using namespace std; + +// Read input image and specify kernel +Mat inputImage = imread("../../examples/conv-opt/images/YuTu.png", IMREAD_GRAYSCALE); +Mat kernel_opencv = Mat(3, 3, CV_32FC1, laplacianKernelAlign); + +// Declare output image +Mat output_opencv; + +// Benchmarking function +static void BM_OpenCV(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + filter2D(inputImage, output_opencv, CV_32FC1, kernel_opencv); + } + } +} + +// Register benchmarking function with different arguments +BENCHMARK(BM_OpenCV)->Arg(1); +BENCHMARK(BM_OpenCV)->Arg(2); +BENCHMARK(BM_OpenCV)->Arg(4); +BENCHMARK(BM_OpenCV)->Arg(8); +BENCHMARK(BM_OpenCV)->Arg(16); + +// Run benchmarks +int main(int argc, char** argv) +{ + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); +} diff --git a/buddy-mlir/Benchmarks/CMakeLists.txt b/buddy-mlir/Benchmarks/CMakeLists.txt new file mode 100644 index 0000000..de15c01 --- /dev/null +++ b/buddy-mlir/Benchmarks/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(BenchmarkFiles) diff --git a/buddy-mlir/Benchmarks/include/ImageProcessing/BuddyContainer.hpp b/buddy-mlir/Benchmarks/include/ImageProcessing/BuddyContainer.hpp new file mode 100644 index 0000000..180ff5e --- /dev/null +++ b/buddy-mlir/Benchmarks/include/ImageProcessing/BuddyContainer.hpp @@ -0,0 +1,39 @@ +#ifndef BUDDY_CONTAINER +#define BUDDY_CONTAINER + +#include <stdint.h> +#include <stdlib.h> + +// Define Memref Descriptor. +typedef struct MemRef_descriptor_ *MemRef_descriptor; +typedef struct MemRef_descriptor_ { + float *allocated; + float *aligned; + intptr_t offset; + intptr_t sizes[2]; + intptr_t strides[2]; +} Memref; + +// Constructor +MemRef_descriptor MemRef_Descriptor(float *allocated, float *aligned, + intptr_t offset, intptr_t sizes[2], + intptr_t strides[2]) { + MemRef_descriptor n = (MemRef_descriptor)malloc(sizeof(*n)); + n->allocated = allocated; + n->aligned = aligned; + n->offset = offset; + for (int i = 0; i < 2; i++) + n->sizes[i] = sizes[i]; + for (int j = 0; j < 2; j++) + n->strides[j] = strides[j]; + + return n; +} + +// Declare the conv2d C interface. +extern "C" { +void _mlir_ciface_conv_2d(MemRef_descriptor input, MemRef_descriptor kernel, + MemRef_descriptor output); +} + +#endif -- GitLab