3

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

但是,当我使用调用 Halide 函数时,我得到了错误:

违反约束:img.stride.0 (520) == 1 (1)
中止(核心转储)

这可以通过将 numpy 数组复制到 Fortran 布局数组来“解决”:

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

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

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

4

2 回答 2

2

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

所以你的选择是改变你的索引以匹配 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)
于 2015-12-23T19:08:55.643 回答
0

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

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

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

于 2015-12-24T11:57:40.827 回答