Встраивание python в fortran 90

Я рассматривал возможность встраивания python в fortran90, чтобы добавить функциональность python в мой существующий код fortran90. Я знаю, что это можно сделать наоборот, расширив python с fortran90, используя f2py из numpy. Но я хочу сохранить свой супер оптимизированный основной цикл в fortran и добавить python, чтобы выполнить некоторые дополнительные задачи / оценить дальнейшие разработки, прежде чем я смогу сделать это в fortran, а также облегчить обслуживание кода. Я ищу ответы на следующие вопросы:

1) Есть ли уже существующая библиотека, из которой я могу встроить python в fortran? (Я в курсе f2py и наоборот) 2) Как мы заботимся о передаче данных из fortran в python и обратно? 3)Как мы можем реализовать функцию обратного вызова? (Позвольте мне немного описать этот сценарий....У меня есть моя программа main_fortran в Fortran, которая вызывает модуль Func1_Python в python. Теперь из этого Func1_Python я хочу вызвать другую функцию...сказать Func2_Fortran в fortran) 4) каково было бы влияние внедрения интерпретатора python внутри fortran с точки зрения производительности....как время загрузки, время выполнения, отправляя данные (большой массив в двойной точности) через etc.

большое спасибо заранее за вашу помощь!!

Edit1: я хочу задать направление обсуждения, добавив дополнительную информацию о работе, которую я делаю. Я занимаюсь научными вычислениями. Итак, я буду много работать над огромным массивы / матрицы с двойной точностью и выполнение операций с плавающей запятой. Таким образом, есть очень мало вариантов, кроме fortran действительно сделать работу за меня. Причина, по которой я хочу включить python в свой код, заключается в том, что я могу использовать NumPy для выполнения некоторых базовых вычислений, если это необходимо, и расширить возможности кода с минимальными усилиями. Например, я могу использовать несколько библиотек, доступных для связи между python и некоторым другим пакетом (скажем, OpenFoam с помощью pyfoam library).

7 ответов


1. Не делай этого!--4-->

Я знаю, что вы хотите добавить код Python внутри программы Fortan, вместо того, чтобы иметь программу Python с расширениями Fortran. Мой первый совет-не делать этого. Fortran быстрее Python в арифметике массивов, но Python легче писать, чем Fortran, легче расширять код Python методами ООП, и Python может иметь доступ к библиотекам, которые важны для вас. Вы упоминаете о супер-оптимизированном основном цикле в Fortran; Fortran отлично подходит для супер-оптимизированного внутренний петли. Логика передачи массива Fortran в программе Python с Numpy намного проще, чем то, что вам нужно сделать, чтобы правильно обрабатывать объект Python в Fortran.

когда я начинаю научный вычислительный проект с нуля, я всегда сначала пишу на Python, выявляю узкие места в производительности и переводю их на Fortran. Возможность тестировать более быстрый код Fortran против проверенного кода Python позволяет легче показать, что код работает правильно.

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

2. Системные вызовы

Если вам абсолютно необходим код Fortran, вызывающий код Python, а не наоборот, самый простой способ сделать это-просто записать код Fortran на диск и запустить код Python с SYSTEM или EXECUTE_COMMAND_LINE. Если вы используете EXECUTE_COMMAND_LINE, вы можете иметь код Python выводить свой результат в stdout, и код Fortran может читать его как символьные данные; если у вас есть много выходных данных (например, большая матрица), для кода Python было бы более разумно выводить файл, который затем читает код Fortran. Накладные расходы на чтение/запись диска могут оказаться непомерно значимыми для этого. Кроме того, вам нужно будет написать код Fortran для вывода ваших данных, код Python для его чтения, код Python для вывода это снова, и код Fortran для повторного ввода данных. Этот код должен быть простым в написании и тестировании, но сохранение этих четырех частей в синхронизации при редактировании кода может обернуться головной болью.

(этот подход опробован в этот вопрос переполнения стека)

3. Встраивание Python в C в Fortran

Я не знаю, как напрямую передать объект Python в память Fortran. Однако код Fortran может вызывать код C, а код C может иметь Python встроен в него. (См. Python учебник по расширению и встраиванию.) В общем, расширение Python (как я рекомендую в пункте 1) предпочтительнее, чем встраивание его в C/C++. (См.Расширение Vs. Встраивание: есть только одно правильное решение.) Заставить это работать будет кошмаром, потому что любые проблемы связи между Python и Fortran могут произойти между Python и C или между C и Fortran. Я не знаю, действительно ли кто-то встраивает Python в C в Fortran, и поэтому получить помощь будет сложно.


Если вы собираетесь встроить Python в Fortran, вам придется сделать это через интерфейс Fortran C; для этого предназначен ISO_C_BINDING. Я бы предостерег от внедрения Python не из-за технических трудностей, а потому, что Python (язык или сообщество) кажется категорически против использования Python в качестве подчиненного языка. Общее мнение заключается в том, что любой язык, не являющийся Python, на котором написан ваш код, должен быть разбит на библиотеки и использоваться для расширения Python, никогда не наоборот. Таким образом, вы увидите (как здесь) больше ответов, пытающихся убедить вас, что вы действительно не хотите делать то, что вы на самом деле хотите сделать, чем фактическая техническая помощь.

Если вам нужна функциональность за пределами самого языка Fortran поддержка (например, операции файловой системы)и вам конкретно не нужен Python и вы хотите язык более выразительный, чем C, вы можете посмотреть на вложение Lua вместо этого. В отличие от Python, Lua специально предназначен для внедрения, поэтому вы, вероятно, столкнетесь с гораздо меньшим социальным и техническим сопротивлением.

есть ряд проектов, которые интеграция Fortran и Lua, самый полный, который я видел на сегодняшний день составляет Aotus. Автор очень отзывчив и процесс интеграции прост.

правда, это не дает ответа на исходный вопрос (как встроить интерпретатор Python в приложение Fortran 90), но, честно говоря, ни один из других ответов тоже. В наши дни я использую Python в качестве своего портативного языка общего назначения, и я бы предпочел придерживаться его при расширении наших основных продуктов (написанных на Fortran). По причинам, изложенным выше, я отказался от попыток внедрить Python и переключился на встраивание Lua; по социальным причинам я чувствую, что Lua-гораздо лучший технический выбор. Это не мой первый выбор, но он работоспособен, по крайней мере в моем случае.

извинения, если я кого-то обидел; я не пытаюсь выбрать бой, просто рассказываю о своем опыте при исследовании этой конкретной темы.


есть очень простой способ сделать это с помощью f2py. Напишите свой метод python и добавьте его в качестве ввода в подпрограмму Fortran. Объявите это в обоих cf2py крюк и объявление типа как EXTERNAL а также как тип возвращаемого значения, например REAL*8. Ваш код Fortran будет иметь указатель на адрес, где хранится метод python. Он будет медленным, как патока, но для тестирования алгоритмов он может быть полезен. Я делаю это часто (я переношу много древних спагетти Fortran модуль Python...) Это также отличный способ использовать такие вещи, как оптимизированные вызовы Scipy в legacy fortran


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

1) встраивание через системный вызов: каждый раз, когда мы хотим получить доступ к python из fortran, мы используем системный вызов для выполнения некоторого скрипта python и обмена данными между ними. Скорость в этом подходе ограничена чтением диска, записью (в этот век оптимизации уровня кэша кода переход на диск смертелен грех.) Кроме того, нам нужно инициализировать интерпретатор каждый раз, когда мы хотим выполнить сценарий, что является значительными накладными расходами. Простой метод Рунге Кутта 4-го порядка, работающий в течение 300 шагов времени, занял колоссальные 59 секунд.

2) переход от Fortran к Python через C: мы используем привязки ISO_C для связи между Fortran и C; и мы вставляем интерпретатор Python внутри C. я получил части его работы, но тем временем я нашел лучший способ и отбросил эту идею. Я бы все же хотелось бы оценить это для полноты картины.

3) Использование f2py для импорта подпрограмм Fortran в Python (расширение) : Здесь мы берем основной цикл из Fortran и кодируем его в Python (Этот подход называется расширением Python с Fortran); и мы импортируем все подпрограммы Fortran в Python с помощью f2py (http://cens.ioc.ee/projects/f2py2e/usersguide/). Мы имеем гибкость иметь самые важные данные в любом научном применении, т. е. внешний цикл (обычно цикл времени) в Python, чтобы мы могли соединить его с другими приложениями. Но у нас также есть недостаток в обмене, возможно, более чем необходимыми данными между Fortran и Python. Тот же пример метода Рунге Кутта 4-го порядка занял 0,372 секунды для выполнения.

4) имитировать врезать через расширять: До сих пор мы видели два чистых подхода встраивания (основной цикл остается в fortran, и мы называем python по мере необходимости) и расширения (основной цикл оставайтесь в python, и мы вызываем fortran по мере необходимости). Есть еще один способ сделать это, который я считаю наиболее оптимальным. Передача частей основного цикла в Python приведет к накладным расходам, которые могут не потребоваться все время. Чтобы избавиться от этих накладных расходов, мы можем сохранить основной цикл в Fortran, который преобразуется в подпрограмму без каких-либо изменений, иметь псевдо-основной цикл в Python, который просто вызывает основной цикл в Fortran, и программа выполняется так, как если бы это был наш нетронутый Fortran программа. При необходимости мы можем использовать функцию обратного вызова, чтобы вернуться в python с необходимыми данными, выполнить скрипт и снова вернуться в fortran. При таком подходе метод Рунге Кутты 4-го порядка занял 0,083 секунды. Я профилировал код и обнаружил, что инициализация интерпретатора python и загрузка заняли 0,075 секунды, а программа заняла всего 0,008 секунды (что включает в себя 300 функций обратного вызова python). Исходный код Фортрана занял 0,007 секунды. Итак, мы получаем почти Fortran работа с Python, как гибкость, используя этот подход.


Я разработал библиотеку Forpy что позволяет использовать Python в Fortran (встраивание). Он использует взаимодействие Fortran C для вызова функций Python C API.

хотя я согласен с тем, что расширение (использование Fortran в Python) часто предпочтительнее, встраивание имеет свои применения:

  • большие, существующие коды Fortran могут потребоваться значительное количество рефакторинга перед их можно использовать из Python-здесь встраивание может сохранить разработку время
  • замена части существующего кода реализацией Python
  • временное встраивание Python для эксперимента с заданным кодом Fortran: например, для тестирования альтернативных алгоритмов или извлечения промежуточных результатов

помимо встраивания, Forpy также поддерживает расширение Python. С Forpy вы можете написать модуль расширения Python полностью в Fortran. Преимущество существующих инструментов, таких как f2py - вы можете использовать Python тип данных (Эл. г. написать функцию, которая принимает список Python в качестве аргумента или функции, которая возвращает питона дикт).

работа с существующими, возможно, устаревшими кодами Fortran часто очень сложна, и я подумайте, что разработчики должны иметь в своем распоряжении инструменты как для встраивания, так и для расширения Python.


Я только что успешно встроил Python в нашу внутреннюю программу ~500 KLOC Fortran с cffi. Важным аспектом было не касаться существующего кода. Программа написана на языке Fortran 95. Я написал тонкую обертку 2003, используя iso_c_binding модуль, который просто импортирует данные из различных модулей, получает указатели C на эти данные и/или обертывает типы Fortran в структуры C, помещает все в один тип / структуру и отправляет в функцию C. Эта функция бывает функция Python, обернутая cffi. Он распаковывает структуру C в более удобный объект Python, обертывает массивы Fortran как массивы Numpy (без копирования), а затем либо падает в интерактивную консоль Python, либо запускает скрипт Python на основе конфигурации пользователя. Нет необходимости писать код C, за исключением одного файла заголовка. Очевидно, что есть некоторые накладные расходы, но эта функциональность предназначена для расширения, а не для производительности.

Я бы посоветовал f2py. Это не поддерживается хорошо и строго ограничивает открытый интерфейс вашего кода Fortran.


Я написал для этого библиотеку,forcallpy, используя слой C, который встраивает функции интерпретации выражений Python, и работая конкретно над аргументами, передаваемыми между Fortran и Python, чтобы сделать вызов скриптов максимально простым (использует встроенную numpy для прямого отображения массивов Fortran внутри ndarrays, используйте имена аргументов, чтобы знать их тип на стороне C/Python).

вы можете увидеть некоторые примеры в документации в readthedocs.

Лоран.