Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ImageProcessing/Rotate] Add Rotate2D and Rotate4D benchmark #137

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions benchmarks/ImageProcessing/BuddyRotate2DBenchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//===------------ BuddyRotate2DBenchmark.cpp ------------------------------===//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//===----------------------------------------------------------------------===//
//
// This file implements the benchmark for Rotate2D operation.
//
//===----------------------------------------------------------------------===//

#include "Kernels.h"
#include <benchmark/benchmark.h>
#include <buddy/Core/Container.h>
#include <buddy/DIP/DIP.h>
#include <buddy/DIP/ImageContainer.h>
#include <buddy/DIP/imgcodecs/loadsave.h>
#include <math.h>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

const float angleRad = M_PI * 30.0 / 180;

// Define the input image.
Img<float, 2> inputBuddyRotate2D;

// Declare the input name.
std::string inputNameBuddyRotate2D;

// Define sizes of input and output.
intptr_t sizesInputBuddyRotate2D[2];
intptr_t sizesOutputBuddyRotate2D[2];

void initializeBuddyRotate2D(char **argv,
Img<float, 2> inputImageBuddyRotate2D) {
inputNameBuddyRotate2D = argv[1];

sizesInputBuddyRotate2D[0] = inputImageBuddyRotate2D.getSizes()[0];
sizesInputBuddyRotate2D[1] = inputImageBuddyRotate2D.getSizes()[1];

float sinAngle = std::sin(angleRad);
float cosAngle = std::cos(angleRad);

sizesOutputBuddyRotate2D[0] =
std::round(std::abs(sizesInputBuddyRotate2D[0] * cosAngle) +
std::abs(sizesInputBuddyRotate2D[1] * sinAngle));
sizesOutputBuddyRotate2D[1] =
std::round(std::abs(sizesInputBuddyRotate2D[0] * sinAngle) +
std::abs(sizesInputBuddyRotate2D[1] * cosAngle));
inputBuddyRotate2D = inputImageBuddyRotate2D;
}

// Benchmarking functions.
static void Buddy_Rotate2D(benchmark::State &state) {
// Define the MemRef descriptor for input and output.
// dip::imread<float, 2>(inputNameBuddyRotate2D, dip::IMGRD_GRAYSCALE);

MemRef<float, 2> outputBuddyRotate2D(sizesOutputBuddyRotate2D);

for (auto _ : state) {
for (int i = 0; i < state.range(0); ++i) {
// Call the MLIR Rotate2D function.
dip::detail::_mlir_ciface_rotate_2d(&inputBuddyRotate2D, angleRad,
&outputBuddyRotate2D);
}
}
}

// Register benchmarking function.
void registerBenchmarkBuddyRotate2D() {
BENCHMARK(Buddy_Rotate2D)->Arg(1)->Unit(benchmark::kMillisecond);
}

// Generate result image.
void generateResultBuddyRotate2D(char **argv, Img<float, 2> input) {
// Define the MemRef descriptors for output.
MemRef<float, 2> output(sizesOutputBuddyRotate2D);

// Run the 2D rotate function.
dip::detail::_mlir_ciface_rotate_2d(&input, angleRad, &output);

intptr_t sizes[2] = {output.getSizes()[0], output.getSizes()[1]};

// Define Img containers for output images.
Img<float, 2> outputImage(output.getData(), sizes);

// Write output to PNG.
bool result = dip::imwrite("ResultBuddyRotate2D.png", outputImage);

if (!result) {
fprintf(stderr, "Exception converting image to PNG format. \n");
}
if (result)
cout << "Saved PNG file." << endl;
else
cout << "ERROR: Can't save PNG file." << endl;
}
170 changes: 170 additions & 0 deletions benchmarks/ImageProcessing/BuddyRotate4DBenchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
//===------------ BuddyRotate4DBenchmark.cpp ------------------------------===//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//===----------------------------------------------------------------------===//
//
// This file implements the benchmark for Rotate4D operation.
//
//===----------------------------------------------------------------------===//

#include "Kernels.h"
#include <benchmark/benchmark.h>
#include <buddy/Core/Container.h>
#include <buddy/DIP/DIP.h>
#include <buddy/DIP/ImageContainer.h>
#include <buddy/DIP/imgcodecs/loadsave.h>
#include <math.h>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

const float angleRad = M_PI * 30.0 / 180;
const int inputBatch = 3;

// Define the input image.
Img<float, 4> inputBuddyRotate4D_NHWC;
Img<float, 4> inputBuddyRotate4D_NCHW;

// Declare the input name.
std::string inputNameBuddyRotate4D;

// Define sizes of input and output.
intptr_t sizesInputBuddyRotate4D_NHWC[4];
intptr_t sizesOutputBuddyRotate4D_NHWC[4];
intptr_t sizesInputBuddyRotate4D_NCHW[4];
intptr_t sizesOutputBuddyRotate4D_NCHW[4];

void initializeBuddyRotate4D(char **argv) {
inputNameBuddyRotate4D = argv[1];

// Read as color image in [HWC] format.
Img<float, 3> inputImage = dip::imread<float, 3>(argv[1], dip::IMGRD_COLOR);
const int inputHeight = inputImage.getSizes()[0];
const int inputWidth = inputImage.getSizes()[1];
const int inputChannel = inputImage.getSizes()[2];

sizesInputBuddyRotate4D_NHWC[0] = sizesInputBuddyRotate4D_NCHW[0] =
inputBatch;
sizesInputBuddyRotate4D_NHWC[1] = sizesInputBuddyRotate4D_NCHW[2] =
inputHeight;
sizesInputBuddyRotate4D_NHWC[2] = sizesInputBuddyRotate4D_NCHW[3] =
inputWidth;
sizesInputBuddyRotate4D_NHWC[3] = sizesInputBuddyRotate4D_NCHW[1] =
inputChannel;

const int inputStride = inputImage.getSize();

Img<float, 4> inputImages_NHWC(sizesInputBuddyRotate4D_NHWC);
auto imagePtr = inputImages_NHWC.getData();
memcpy(imagePtr, inputImage.getData(), inputStride * sizeof(float));
for (int i = 1; i < inputBatch; i++) {
Img<float, 3> input = dip::imread<float, 3>(argv[1], dip::IMGRD_COLOR);
memcpy(imagePtr + i * inputStride, input.getData(),
inputStride * sizeof(float));
}

float sinAngle = std::sin(angleRad);
float cosAngle = std::cos(angleRad);
const int outputHeight =
std::round(std::abs(inputImage.getSizes()[0] * cosAngle) +
std::abs(inputImage.getSizes()[1] * sinAngle));
const int outputWidth =
std::round(std::abs(inputImage.getSizes()[0] * sinAngle) +
std::abs(inputImage.getSizes()[1] * cosAngle));

sizesOutputBuddyRotate4D_NHWC[0] = sizesOutputBuddyRotate4D_NCHW[0] =
inputBatch;
sizesOutputBuddyRotate4D_NHWC[1] = sizesOutputBuddyRotate4D_NCHW[2] =
outputHeight;
sizesOutputBuddyRotate4D_NHWC[2] = sizesOutputBuddyRotate4D_NCHW[3] =
outputWidth;
sizesOutputBuddyRotate4D_NHWC[3] = sizesOutputBuddyRotate4D_NCHW[1] =
inputChannel;

inputBuddyRotate4D_NHWC = inputImages_NHWC;

Img<float, 4> inputImages_NCHW(sizesInputBuddyRotate4D_NCHW);
dip::detail::Transpose<float, 4>(&inputImages_NCHW, &inputImages_NHWC,
{0, 3, 1, 2});
inputBuddyRotate4D_NCHW = inputImages_NCHW;
}

// Benchmarking functions.
static void Buddy_Rotate4D_NHWC(benchmark::State &state) {
MemRef<float, 4> outputBuddyRotate4D(sizesOutputBuddyRotate4D_NHWC);

for (auto _ : state) {
for (int i = 0; i < state.range(0); ++i) {
// Call the MLIR Rotate4D function.
dip::detail::_mlir_ciface_rotate_4d_nhwc(&inputBuddyRotate4D_NHWC,
angleRad, &outputBuddyRotate4D);
}
}
}

static void Buddy_Rotate4D_NCHW(benchmark::State &state) {
MemRef<float, 4> outputBuddyRotate4D(sizesOutputBuddyRotate4D_NCHW);

for (auto _ : state) {
for (int i = 0; i < state.range(0); ++i) {
// Call the MLIR Rotate4D function.
dip::detail::_mlir_ciface_rotate_4d_nchw(&inputBuddyRotate4D_NCHW,
angleRad, &outputBuddyRotate4D);
}
}
}

// Register benchmarking function.
void registerBenchmarkBuddyRotate4D() {
BENCHMARK(Buddy_Rotate4D_NHWC)->Arg(1)->Unit(benchmark::kMillisecond);
BENCHMARK(Buddy_Rotate4D_NCHW)->Arg(1)->Unit(benchmark::kMillisecond);
}

// Generate result image.
void generateResultBuddyRotate4D(char **argv) {
// Define the MemRef descriptors for output.
MemRef<float, 4> output_NHWC(sizesOutputBuddyRotate4D_NHWC);

// Run the 4D rotate function.
dip::detail::_mlir_ciface_rotate_4d_nhwc(&inputBuddyRotate4D_NHWC, angleRad,
&output_NHWC);

intptr_t imageSizes[3] = {output_NHWC.getSizes()[1],
output_NHWC.getSizes()[2],
output_NHWC.getSizes()[3]};
Img<float, 3> image_NHWC(output_NHWC.getData(), imageSizes);

// Write output to PNG.
bool result = dip::imwrite("ResultBuddyRotate4D_NHWC.png", image_NHWC);

MemRef<float, 4> output_NCHW(sizesOutputBuddyRotate4D_NCHW);

dip::detail::_mlir_ciface_rotate_4d_nchw(&inputBuddyRotate4D_NCHW, angleRad,
&output_NCHW);

dip::detail::Transpose<float, 4>(&output_NHWC, &output_NCHW, {0, 2, 3, 1});

Img<float, 3> image_NCHW(output_NHWC.getData(), imageSizes);

result = dip::imwrite("ResultBuddyRotate4D_NCHW.png", image_NCHW);

if (!result) {
fprintf(stderr, "Exception converting image to PNG format. \n");
}
if (result)
cout << "Saved PNG file." << endl;
else
cout << "ERROR: Can't save PNG file." << endl;
}
3 changes: 3 additions & 0 deletions benchmarks/ImageProcessing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ add_executable(image-processing-benchmark
BuddyMorph2DBenchmark.cpp
OpenCVMorph2DBenchmark.cpp
BuddyResize2DBenchmark.cpp
BuddyRotate2DBenchmark.cpp
BuddyRotate4DBenchmark.cpp
OpenCVResize2DBenchmark.cpp
OpenCVRotate2DBenchmark.cpp
)

target_include_directories(image-processing-benchmark
Expand Down
18 changes: 18 additions & 0 deletions benchmarks/ImageProcessing/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,17 @@ void initializeOpenCVMorph2D(char **);
void initializeOpenCVFilter2D(char **);
void initializeEigenConvolve2D(char **, Img<float, 2>);
void initializeBuddyResize2D(char **, Img<float, 2>);
void initializeBuddyRotate2D(char **, Img<float, 2>);
void initializeBuddyRotate4D(char **);
void initializeOpenCVResize2D(char **);
void initializeOpenCVRotate2D(char **);

void generateResultMLIRConv2D(Img<float, 2>);
void generateResultBuddyConv2D(Img<float, 2>);
void generateResultBuddyCorr2D(char **argv, Img<float, 2>);
void generateResultBuddyResize2D(char **argv, Img<float, 2>);
void generateResultBuddyRotate2D(char **argv, Img<float, 2>);
void generateResultBuddyRotate4D(char **);
void generateResultBuddyErosion2D(char **, Img<float, 2>);
void generateResultBuddyOpening2D(char **, Img<float, 2>);
void generateResultBuddyClosing2D(char **, Img<float, 2>);
Expand All @@ -57,6 +62,7 @@ void generateResultOpenCVTopHat2D();
void generateResultOpenCVBottomHat2D();
void generateResultOpenCVMorphGrad2D();
void generateResultOpenCVResize2D();
void generateResultOpenCVRotate2D();
void generateResultEigenConvolve2D();

void registerBenchmarkBuddyCorr2D();
Expand All @@ -76,7 +82,10 @@ void registerBenchmarkOpenCVBottomHat2D();
void registerBenchmarkOpenCVMorphGrad2D();
void registerBenchmarkOpenCVFilter2D();
void registerBenchmarkBuddyResize2D();
void registerBenchmarkBuddyRotate2D();
void registerBenchmarkBuddyRotate4D();
void registerBenchmarkOpenCVResize2D();
void registerBenchmarkOpenCVRotate2D();

// Run benchmarks.
int main(int argc, char **argv) {
Expand All @@ -103,12 +112,18 @@ int main(int argc, char **argv) {
initializeOpenCVFilter2D(argv);
initializeEigenConvolve2D(argv, img);
initializeBuddyResize2D(argv, img);
initializeBuddyRotate2D(argv, img);
initializeBuddyRotate4D(argv);
initializeOpenCVResize2D(argv);
initializeOpenCVRotate2D(argv);

registerBenchmarkBuddyCorr2D();
registerBenchmarkOpenCVFilter2D();
registerBenchmarkBuddyResize2D();
registerBenchmarkBuddyRotate2D();
registerBenchmarkBuddyRotate4D();
registerBenchmarkOpenCVResize2D();
registerBenchmarkOpenCVRotate2D();
registerBenchmarkBuddyErosion2D();
registerBenchmarkBuddyDilation2D();
registerBenchmarkBuddyOpening2D();
Expand All @@ -131,6 +146,8 @@ int main(int argc, char **argv) {
generateResultOpenCVFilter2D();
generateResultBuddyConv2D(img);
generateResultBuddyCorr2D(argv, img);
generateResultBuddyRotate2D(argv, img);
generateResultBuddyRotate4D(argv);
generateResultBuddyResize2D(argv, img);
generateResultBuddyErosion2D(argv, img);
generateResultBuddyDilation2D(argv, img);
Expand All @@ -147,6 +164,7 @@ int main(int argc, char **argv) {
generateResultOpenCVOpening2D();
generateResultOpenCVClosing2D();
generateResultOpenCVResize2D();
generateResultOpenCVRotate2D();
generateResultEigenConvolve2D();

return 0;
Expand Down
Loading