我正在尝试使用 Metal 作为我在 iOS 上使用的提前 (AOT) Halide 管道的目标。
我已经成功创建了一个 Halide 生成器,它使用 Metal 生成静态二进制文件。我可以在我的 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
调用Halide函数的iOS代码
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_
buffer 的值为 200。返回 output_
buffer 应该是 225,但事实并非如此。所有值都只有 25。
我应该注意到,当在我的笔记本电脑的 GPU 和手机的 CPU 上运行时,它可以正常工作。唯一的区别是 Halide 发生器target
.
关于为什么 Input<Buffer<uint8_t>> input
的任何想法运行 Halide 函数时似乎被设置为全零?
调试语句似乎在设备端分配内存,但我没有看到明确的语句说 halide_copy_to_device
.
最佳答案
如果在Buffer
中设置值,则需要将其标记为脏:input_.set_host_dirty()
关于c++ - 在 iOS 上将 Halide 提前 (AOT) 与 Metal 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44165463/