Halide с массивами numpy макета C

Я начинаю использовать Halide и использую его в среде Python. В этой среде Python данные передаются как массивы Numpy, которые на самом деле являются псевдонимом массива C++, определенного в другом месте.

Однако, когда я использую вызов функции Halide, я получаю сообщение об ошибке:

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

который можно «решить», скопировав массивы numpy в массивы макетов Fortran:

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

с img и res мои входные и выходные изображения. Однако обратите внимание, что это включает в себя дополнительные операции копирования, что очень плохо для общего доступа к глобальной памяти.

Как я могу обойти эту проблему? Я думал о том, чтобы на самом деле сообщить Python, что мои массивы имеют формат Fortran и имеют правильное переключение индексов.... Однако в настоящее время я использую PyArray_SimpleNewFromData для получения массивов Python (без фактического копирования данных), и это приводит к Массивы в стиле C.


person Klamer Schutte    schedule 23.12.2015    source источник
comment
Если вы считаете одну дополнительную операцию копирования «действительно плохой», вам не следует использовать python/numpy, поскольку накладные расходы такого рода в значительной степени связаны с территорией. Тем не менее, вы проверили, является ли это вашим узким местом? Если это так, вы должны использовать галогенид для некоторых довольно тривиальных операций. Напрашивается вопрос, почему вы так озабочены производительностью в первую очередь?   -  person Eelco Hoogendoorn    schedule 23.12.2015
comment
Eelco, с приведенными ниже решениями (т. е. изменение шага без копирования данных) накладные расходы сократились до 0,25 мс для плавающего изображения 512x512, тогда как раньше они составляли около 7,5 мс. Halide занимается улучшением локализации данных и сокращением использования полосы пропускания, поэтому мы должны стараться избегать дополнительных копий изображений. Обратите внимание, что я ожидаю, что np.copy будет очень плохим из-за его операции транспонирования. Возможно, нам следует повторно реализовать np.copy с помощью Halide, чтобы повысить его производительность...   -  person Klamer Schutte    schedule 24.12.2015


Ответы (2)


Halide изначально предполагает хранение по строкам, но индексирует такие вещи, как: im(col, row)... и это очень похоже на хранение по столбцам для тех, кто привык рассматривать изображения как матрицы или использовать 2D-массивы в C.

Таким образом, вы можете изменить свою индексацию, чтобы она соответствовала понятию Halide, или сообщить Halide, что ваша структура памяти наоборот (шаг (0) велик).

Здесь есть учебник, посвященный тесно связанной теме: http://halide-lang.org/tutorials/tutorial_lesson_16_rgb_generate.html

Краткая версия для 2D-вводов и функций:

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 во втором измерении, потому что это единственное. это плотно в памяти:

f(i, j) = ...
f.vectorize(j, 4)
person Andrew Adams    schedule 23.12.2015

Проблема в том, что PyArray_SimpleNewFromData создал ndarray в стиле C из данных, где в коде хоста C++ массивы в стиле Fortran. Решение состоит в том, чтобы преобразовать ndarrays сразу после их создания, что можно сделать с помощью кода, например:

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

После этого в Halide мы можем нормально векторизовать в нулевом (x) измерении.

person Klamer Schutte    schedule 24.12.2015