Skip to content

Commit

Permalink
Merge pull request #4 from zpye/halide
Browse files Browse the repository at this point in the history
add Halide support
  • Loading branch information
zpye committed Jun 5, 2023
2 parents 22c8d83 + f034433 commit 1b71475
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 19 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ pip install build/python/
python test/test_python/test_model.py
```

## (Experimental) Halide Programming

Note: Only upsample nearest layer has an implementation of Halide.

1. Set environment `HALIDE_ROOT` for Halide installation path, using release packages from [https://github.com/halide/Halide/releases](https://github.com/halide/Halide/releases) is a good choice.

2. Set `--halide=true` after `xmake config` and build:

```shell
xmake config -a x64 -m release --halide=true
xmake -w --all
```

## Reference

[KuiperInfer](https://github.com/zjhellofss/KuiperInfer) -> basic framework
Expand All @@ -75,4 +88,6 @@ python test/test_python/test_model.py

[stb](https://github.com/nothings/stb) -> image loader and image writer

[Halide](https://github.com/halide/Halide) -> Halide programming

[tmp](https://github.com/zjhellofss/tmp) -> pnnx models
25 changes: 25 additions & 0 deletions src/layer/halide/halide_upsample_nearest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "Halide.h"

class HalideUpsampleNearest : public Halide::Generator<HalideUpsampleNearest> {
public:
Input<float> scale_x{"scale_x"};
Input<float> scale_y{"scale_y"};

Input<Halide::Buffer<float, 4>> input{"input"};

Output<Halide::Buffer<float, 4>> output{"output"};

Halide::Var b, y, x, c;

void generate() {
Halide::Expr x_scale =
Halide::cast<int32_t>(Halide::cast<float>(x) * scale_x);
Halide::Expr y_scale =
Halide::cast<int32_t>(Halide::cast<float>(y) * scale_y);

// TODO: schedule
output(c, x, y, b) = input(c, x_scale, y_scale, b);
}
};

HALIDE_REGISTER_GENERATOR(HalideUpsampleNearest, halide_upsample_nearest)
16 changes: 16 additions & 0 deletions src/layer/halide/xmake.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
target("halide_upsample_nearest")
set_kind("binary")
set_targetdir("$(buildir)/")
add_files("halide_upsample_nearest.cc", "$(env HALIDE_ROOT)/share/Halide/tools/GenGen.cpp")
add_options("halide")

after_build(function ()
os.run("xmake run halide_upsample_nearest -g halide_upsample_nearest -o . -f halide_upsample_nearest target=host")
end)

target("halide_layers")
set_kind("headeronly")
add_defines("USE_HALIDE", { public = true })
add_includedirs("$(env HALIDE_ROOT)/include/", "$(buildir)/", { public = true })
add_linkdirs("$(buildir)/", { public = true })
add_links("halide_upsample_nearest", { public = true })
25 changes: 25 additions & 0 deletions src/layer/upsample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

#include <cmath>

#if defined(USE_HALIDE)
#include "HalideBuffer.h"
#include "halide_upsample_nearest.h"
#endif

namespace SimpleInfer {

DEFINE_LAYER_REGISTRY(Upsample);
Expand Down Expand Up @@ -119,6 +124,25 @@ Status Upsample::Forward(const Tensor& input, Tensor& output) {
const float scale_factor_w_inv = 1.0f / scale_factor_w_;

// nearest
#if defined(USE_HALIDE)
Halide::Runtime::Buffer<float> input_buffer(
input_eigen_tensor.data(),
{input_channel, input_width, input_height, input_batch});

Halide::Runtime::Buffer<float> output_buffer(
output_eigen_tensor.data(),
{output_channel, output_width, output_height, output_batch});

int ret = halide_upsample_nearest(scale_factor_w_inv,
scale_factor_h_inv,
input_buffer,
output_buffer);
if (0 != ret) {
LOG(ERROR) << "error in halide_upsample_nearest: " << ret;
return Status::kFail;
}

#else
#if 0
for (int h = 0; h < output_height; ++h) {
int h_in = (float)h * scale_factor_h_inv;
Expand All @@ -140,6 +164,7 @@ Status Upsample::Forward(const Tensor& input, Tensor& output) {
output_eigen_tensor.device(*device) = output_eigen_tensor.generate(
Nearest4D(input_eigen_tensor, scale_factor_h_inv, scale_factor_w_inv));
#endif
#endif // USE_HALIDE

return Status::kSuccess;
}
Expand Down
4 changes: 2 additions & 2 deletions test/test_layer/test_upsample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <algorithm>
#include <cmath>

TEST_CASE("Test Upsample layer 0") {
TEST_CASE("Test Upsample layer 0", "[Upsample]") {
using namespace SimpleInfer;

// set tensor
Expand Down Expand Up @@ -53,7 +53,7 @@ TEST_CASE("Test Upsample layer 0") {
}
}

TEST_CASE("Test Upsample layer 1") {
TEST_CASE("Test Upsample layer 1", "[Upsample]") {
using namespace SimpleInfer;

// set tensor
Expand Down
54 changes: 37 additions & 17 deletions xmake.lua
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
add_rules("mode.debug", "mode.release")

set_languages("cxx17")

option("build_python")
set_default(false)
set_showmenu(true)
option_end()

option("halide")
set_default(false)
set_showmenu(true)
add_includedirs("$(env HALIDE_ROOT)/include/", { public = true })
add_linkdirs("$(env HALIDE_ROOT)/bin/Release/",
"$(env HALIDE_ROOT)/lib/Release/", { public = true })
add_links("Halide")
add_rpathdirs("$(env HALIDE_ROOT)/bin/Release/")
option_end()

includes("3rdparty")

if has_config("halide") then
includes("src/layer/halide")
end

target("simple-infer")
set_kind("static")
add_includedirs("include/", { public = true })
Expand All @@ -17,28 +33,32 @@ target("simple-infer")
add_vectorexts("sse", "sse2", "sse3", "ssse3")
add_vectorexts("avx", "avx2")

if has_config("halide") then
add_deps("halide_layers")
end

target("tools")
set_kind("static")
add_includedirs("tools/", { public = true })
add_files("tools/**.cpp")

if has_config("build_python") then
target("pybind11_export")
before_build(function ()
os.cp("python/simpleinfer/", "$(buildir)/python/")
end)

set_kind("shared")
set_basename("simpleinfer")
set_extension(".pyd")
set_targetdir("$(buildir)/python/simpleinfer")
add_files("python/pybind11_main.cpp")
add_deps("pybind11", "simple-infer")

after_build(function ()
os.cp("python/setup.py.in", "$(buildir)/python/setup.py")
end)
end
if has_config("build_python") then
target("pybind11_export")
before_build(function ()
os.cp("python/simpleinfer/", "$(buildir)/python/")
end)

set_kind("shared")
set_basename("simpleinfer")
set_extension(".pyd")
set_targetdir("$(buildir)/python/simpleinfer")
add_files("python/pybind11_main.cpp")
add_deps("pybind11", "simple-infer")

after_build(function ()
os.cp("python/setup.py.in", "$(buildir)/python/setup.py")
end)
end

-- tests
target("test-eigen")
Expand Down

0 comments on commit 1b71475

Please sign in to comment.