openlang

f2py копирует мой C-массив при каждом вызове

Передаю массив NumPy в подпрограмму на Фортране через f2py. Массив создан как обычно, np.zeros((n, m)), то есть в C-порядке. Фортран хочет, чтобы подряд лежали столбцы. f2py это знает и для обычного входного аргумента без единого слова делает поэлементную копию в нужном порядке. Никакого предупреждения. Работает, числа верные. Просто каждый вызов в цикле копирует матрицу.

С intent(inout) хуже, но честнее. Копия там проглотила бы изменения, поэтому f2py требует правильно расположенный массив, а иначе бросает исключение. Лечится через order='F' при создании или один вызов np.asfortranarray до цикла.

Старая история про порядок по столбцам, только на этот раз на стыке двух языков, и платишь за неё копией на каждом вызове.

Раздражает. Лучше бы уж предупреждение.

Разговор продолжается 3

Следуя доводам
  1. Ссылка на ответ

    Одномерные массивы не в счёт. Непрерывный вектор одновременно C- и F-непрерывен. Копии нет. Проблемы начинаются со второго ранга.

  2. Ссылка на ответ

    Фортран я знаю поверхностно, но интересно, сколько копий на самом деле делает цикл. В документации f2py пример собирают с -DF2PY_REPORT_ON_ARRAY_COPY=1, и тогда обёртка печатает сообщение, когда копирует массив. Переверните порядок и больше ничего не трогайте, а потом снова посчитайте сообщения.

    И ещё случай для проверки. Срез вроде a[:, ::2], взятый уже после np.asfortranarray, перестаёт быть непрерывным, так что копия, по-моему, вернётся. Но лучше увидеть сообщения, чем гадать.

  3. Ссылка на ответ

    Флаг от mtsuda тут как раз то, что нужно. С -DF2PY_REPORT_ON_ARRAY_COPY=1 C-массив даёт сообщение о копии на каждом вызове, один np.asfortranarray до цикла его глушит, а срез a[:, ::2] снова копируется, как и предсказано выше.

    Есть ещё подвох. Тот же срез в intent(inout) падает с исключением, хотя исходный массив в F-порядке, потому что intent(inout) требует непрерывный массив, а срез с шагом таковым не является.

Другие стороны того же вопроса

  1. sum(X) на матрице из одной строки

    Функция берёт матрицу наблюдений, строки - наблюдения, столбцы - признаки, и нормирует каждый столбец через X ./ sum(X). Долг…

    Ответы 6matlab
  2. na.rm = TRUE на группе, где всё NA

    Итоги по группам через tapply(x, g, sum, na.rm = TRUE), и одна группа вернулась с 0. Все значения в ней NA. Ни одного измерен…

    Ответы 4r
  3. Цикл, который выделял память на каждый столбец

    Срезы в Julia копируют. Это известно, но внутри цикла вылетело из головы. Возьмём функцию, которая идёт по столбцам матрицы и…

    Ответы 4julia