在iOS上使用Metal提前使用Halide(AOT)

时间:2017-05-24 17:55:18

标签: c++ ios halide

我正在尝试使用Metal作为我在iOS上使用的提前(AOT)Halide管道的目标。

我已经成功创建了一个使用Metal生成静态二进制文件的Halide生成器。我可以在我的iOS应用程序中链接并调用此二进制文件。

然而,当我将Buffer<uint8_t> input_传递给函数时,Buffer中的数据在GPU端似乎总是为零。请注意,这仅在iOS上的GPU上运行时才会发生。

发电机

#include "Halide.h"

using namespace Halide;

class MyHalideTest : public Halide::Generator<MyHalideTest> {
public:
    Input<Buffer<uint8_t>> input{"input", 3};
    Input<int32_t> width{"width"};
    Input<int32_t> height{"height"};
    Output<Buffer<uint8_t>> output{"output", 3};

    void generate() {
        output(x,y,c) = cast<uint8_t>(input(x,y,c)+25);
    }

    void schedule() {
        input
            .dim(0).set_stride(4)
            .dim(2).set_stride(1).set_bounds(0, 4);
        output
            .dim(0).set_stride(4)
            .dim(2).set_stride(1).set_bounds(0, 4);

        if (get_target().has_gpu_feature()) {
            output
                .reorder(c, x, y)
                .bound(c, 0, 4)
                .unroll(c);
            output.gpu_tile(x, y, xo, yo, xi, yi, 16, 16);
        }
        else {
            output
                .reorder(c, x, y)
                .unroll(c)
                .split(y, yo, yi, 16)
                .parallel(yo)
                .vectorize(x, 8);
        }
    }

private:
    Var x{"x"}, y{"y"}, c{"c"}, xi{"xi"}, xo{"xo"}, yi{"yi"}, yo{"yo"};

};

HALIDE_REGISTER_GENERATOR(MyHalideTest, "halide_test")

生成生成器的命令行

./MyHalideTest_generator -g halide_test \
-f halide_test_ARM64_metal \
-n halide_test_ARM64_metal \
-o "${DERIVED_FILE_DIR}" \
target=arm-64-ios-metal-debug-user_context

iOS代码调用Halide功能

Buffer<uint8_t> input_;
Buffer<uint8_t> output_;

// Other setup

- (void)initBuffersWithWidth:(int)w height:(int)h using_metal:(bool)using_metal
{
    // We really only need to pad this for the use_metal case,
    // but it doesn't really hurt to always do it.
    const int c = 4;
    const int pad_pixels = (64 / sizeof(int32_t));
    const int row_stride = (w + pad_pixels - 1) & ~(pad_pixels - 1);
    const halide_dimension_t pixelBufShape[] = {
        {0, w, c},
        {0, h, c * row_stride},
        {0, c, 1}
    };

    input_ = Buffer<uint8_t>(nullptr, 3, pixelBufShape);
    input_.allocate();
    auto buf = input_.raw_buffer()->host;
    memset(buf, 200, input_.size_in_bytes());

    // This allows us to make a Buffer with an arbitrary shape
    // and memory managed by Buffer itself
    output_ = Buffer<uint8_t>(nullptr, 3, pixelBufShape);
    output_.allocate();
}

...

/** Calling Halide function here **/
halide_test((__bridge void *)self, input_, width, height, output_);
output_.copy_to_host();

// Display output image...

因此,代码将input_缓冲区设置为值200.返回的output_缓冲区应为225,但事实并非如此。所有值都只有25。

我应该注意,当我的笔记本电脑的GPU和手机的CPU上运行时,它正常 。唯一的区别是Halide生成器target

运行Halide函数时,Input<Buffer<uint8_t>> input为什么似乎设置为全零的任何想法?

调试语句似乎是设备端的malloc内存,但我没有看到halide_copy_to_device的明确声明。

1 个答案:

答案 0 :(得分:3)

如果您在Buffer中设置值,则需要将其标记为脏:input_.set_host_dirty()

相关问题