Ускорение циклов по массиву Numpy

В моем коде у меня есть цикл, который индексирует многомерный массив numpy и выполняет некоторую операцию с использованием подматрицы, которая получается на каждой итерации. Похоже, это

for sub in Arr: #do stuff using sub 

Теперь материал, который делается с помощью sub , полностью векторизован, поэтому он должен быть эффективным. С другой стороны, эта петля повторяется примерно в ~10^5 раз и является узким местом. Думаете ли вы, что я получу улучшение, выгрузив эту часть на C. Я немного неохотно это делаю, потому что do stuff using sub вещания, нарезки, умных индексирующих трюков, которые были бы утомительными для написания на простом C. Я бы тоже приветствовать мысли и предложения о том, как бороться с трансляцией, нарезкой, интеллектуальным индексированием при выгрузке вычислений на C.

3 Solutions collect form web for “Ускорение циклов по массиву Numpy”

Сан вы можете взглянуть на scipy.weave . Вы можете использовать scipy.weave.blitz чтобы трансформировать ваше выражение в код C++ и запустить его. Он будет обрабатывать резки автоматически и избавиться от временных, но вы утверждаете, что тело вашего цикла for не создает временные интервалы, поэтому ваше перемещение может отличаться.

Однако, если вы хотите заменить весь цикл for на что-то более эффективное, вы можете использовать scipy.inline . Недостатком является то, что вам нужно написать код на C++ . Это не должно быть слишком сложно, потому что вы можете использовать синтаксис Blitz++ который очень близок к выражениям массива numpy. Нарезка поддерживается напрямую, однако вещание – нет.

Есть две работы:

  1. заключается в использовании numpy-C api и использовании многомерных итераторов. Они прозрачно обрабатывают вещание. Однако вы вызываете среду выполнения Numpy, поэтому могут возникнуть некоторые накладные расходы. Другой вариант и, возможно, более простой вариант – использовать стандартную матричную нотацию для трансляции. Трансляционные операции могут быть записаны как внешние продукты с вектором всех единиц. Хорошо, что Blitz++ самом деле не создаст эти временные широковещательные массивы в памяти, он выяснит, как превратить его в эквивалентный цикл.

  2. Для второго варианта ознакомьтесь с http://www.oonumerics.org/blitz/docs/blitz_3.html#SEC88 для владельцев индексных площадок. Пока ваша матрица имеет менее 11 размеров, вы в порядке. Эта ссылка показывает, как их можно использовать для создания внешних продуктов http://www.oonumerics.org/blitz/docs/blitz_3.html#SEC99 (поиск внешних продуктов для перехода к соответствующей части документа).

Если вы не можете «векторизовать» всю операцию, и цикл является действительно узким местом, я настоятельно рекомендую использовать Cython. Я недавно занимался этим, и с ним просто работать, и у него есть достойный интерфейс с numpy. Для чего-то вроде интегратора langevin я видел 115-кратное ускорение над достойной реализацией в numpy. Смотрите документацию здесь:

http://docs.cython.org/src/tutorial/numpy.html

и я также рекомендую посмотреть следующую статью

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

Помимо использования Cython, вы можете написать часть (-и) бутылочки в Фортране. Затем используйте f2py, чтобы скомпилировать его в файл Python .pyd.

  • Создание регулярной сетки Delaunay в scipy
  • pandas сводная таблица продаж
  • Матричное умножение на CPU (numpy) и GPU (gnumpy) дает разные результаты
  • python + numpy: почему numpy.log выдает ошибку атрибута, если его операнд слишком велик?
  • fminunc чередуется в numpy
  • Интерполяция обратного расстояния (IDW) с Python
  • Как преобразовать этот массив (100, 100) numpy в оттенок серого в pygame?
  • Как распределить входные массивы с помощью f2py?
  • Python - лучший язык программирования в мире.