卤化物与 C 布局 numpy 数组

Halide with C layout numpy arrays

我开始使用 Halide 并在 Python 环境中使用它。在那个 Python 环境中,数据作为 Numpy 数组传递,实际上是别处定义的 C++ 数组的别名。

但是,当我调用 Halide 函数时出现错误:

Constraint violated: img.stride.0 (520) == 1 (1)
Aborted (core dumped)

可以通过将 numpy 数组复制到 Fortran 布局数组来 "solved":

img=np.copy(img,order="F")
res=np.copy(res,order="F")

使用 img 和 res 我的输入和输出图像。但是请注意,这涉及额外的复制操作,这对整体全局内存访问非常不利。

如何避免这个问题?我一直在考虑的一种方法是实际告诉 Python 我的数组具有 Fortran 布局并正确切换索引......但是,我目前使用 PyArray_SimpleNewFromData 来获取 Python数组(实际上没有复制数据)并导致 C 样式数组。

Halide 本身期望行优先存储,但索引如下:im(col, row)... 对于习惯将图像视为矩阵或使用的人来说,这看起来非常像列优先存储C 中的二维数组

所以你的选择是改变你的索引以匹配 Halide 的概念,或者告诉 Halide 你的内存布局是相反的(stride(0) 很大)。

此处有一个涵盖密切相关主题的教程:http://halide-lang.org/tutorials/tutorial_lesson_16_rgb_generate.html

2D 输入和 Funcs 的简短版本是:

image_param.set_stride(0, Expr()).set_stride(1, 1);
output_func.output_buffer().set_stride(0, Expr()).set_stride(1, 1);

第一个 set_stride 调用取消约束维度 0 中的步幅,第二个调用告诉 Halide 它可以假设维度 1 中的步幅为 1。如果你这样做,你会想要向量化你的 Halide Funcs跨越第二个维度,因为那是记忆中密集的维度:

f(i, j) = ...
f.vectorize(j, 4)

问题是 PyArray_SimpleNewFromData 从数据中创建了一个 C 风格的 ndarray,而在主机 C++ 代码中,数组是 Fortran 风格的。一种解决方案是在创建 ndarrays 后立即对其进行转换,这可以通过以下代码完成:

def swap(img):
    (sh1,sh2)=img.shape
    (st1,st2)=img.strides
    img.shape=(sh2,sh1)
    img.strides=(st2,st1)

在此之后,在 Halide 中我们通常可以在零 (x) 维度中进行矢量化。