Я пытаюсь использовать функцию extern в Halide. В моем контексте я хочу сделать это на GPU.
Я компилирую в компиляции AOT с оператором opencl. Конечно, opencl все еще может использовать процессор, поэтому я использую это:
halide_set_ocl_device_type("gpu");
На данный момент все запланировано в calculate_root().
Первый вопрос: если я использую calculate_root() и OpenCL gpu, будет ли мой процесс вычисляться на устройстве с некоторыми CopyHtoD и DtoH? (Или это будет в буфере хоста)
Второй вопрос, больше связанный с внешними функциями. Мы используем некоторый внешний вызов, потому что часть нашего алгоритма не реализована в Halide. Внешний вызов:
foo.define_extern("cool_foo", args, Float(32), 4);
Внешнее извлечение: extern "C" int cool_foo(buffer_t * in, int w, int h, int z, buffer_t * out){ .. }
Но, в функции cool_foo, мой buffer_t загружается только в память хоста. Адрес разработчика — 0 (по умолчанию).
Если я попытаюсь скопировать память перед алгоритмом:
halide_copy_to_dev(NULL, &in);
Это ничего не делает.
Если я сделаю доступной только память устройства:
in.host = NULL;
Мой указатель хоста равен нулю, но адрес устройства по-прежнему равен 0.
(в моем случае dev_dirty истинно, а host_dirty ложно)
Есть идеи?
РЕДАКТИРОВАТЬ (чтобы ответить dsharlet)
Вот структура моего кода:
Правильно анализировать данные на ЦП. --> Отправил буфер на GPU (используя halide_copy_to_dev...) --> Войдите в структуру Halide, прочитайте параметр и добавьте граничное условие --> Зайдите в мою внешнюю функцию -->...
У меня нет действительного buffer_t в моей внешней функции. Я планирую все в calculate_root(), но использую HL_TARGET=host-opencl и устанавливаю ocl на gpu. Перед входом в Halide я могу прочитать адрес своего устройства, и все в порядке.
Вот мой код:
До Halide все было процессором (указатель), и мы перенесли его на GPU.
buffer_t k = { 0, (uint8_t *) k_full, {w_k, h_k, num_patch_x * num_patch_y * 3}, {1, w_k, w_k * h_k}, {0}, sizeof(float), };
#if defined( USEGPU )
// Transfer into GPU
halide_copy_to_dev(NULL, &k);
k.host_dirty = false;
k.dev_dirty = true;
//k.host = NULL; // It's k_full
#endif
halide_func(&k)
Внутри Галида:
ImageParam ...
Func process;
process = halide_sub_func(k, width, height, k.channels());
process.compute_root();
...
Func halide_sub_func(ImageParam k, Expr width, Expr height, Expr patches)
{
Func kBounded("kBounded"), kShifted("kShifted"), khat("khat"), khat_tuple("khat_tuple");
kBounded = repeat_image(constant_exterior(k, 0.0f), 0, width, 0, height, 0, patches);
kShifted(x, y, pi) = kBounded(x + k.width() / 2, y + k.height() / 2, pi);
khat = extern_func(kShifted, width, height, patches);
khat_tuple(x, y, pi) = Tuple(khat(0, x, y, pi), khat(1, x, y, pi));
kShifted.compute_root();
khat.compute_root();
return khat_tuple;
}
За пределами галоида (функция Extern):
inline ....
{
//The buffer_t.dev and .host are 0 and null. I expect a null from the host, but the dev..
}