Я использую f2py для интеграции некоторых подпрограмм Fortran77 в мой модуль python, но не могу найти хороший способ решить следующую проблему. Мои подпрограммы на Фортране уничтожают все входные массивы в ходе вычислений. Я хотел бы предложить пользователю как возможность использовать эффективное с памятью поведение «на месте» этих подпрограмм, так и возможность выполнить подпрограмму, не уничтожая свои данные на стороне Python.
Я могу придумать два способа сделать это:
- Если пользователь не хочет, чтобы входные данные были уничтожены, создайте резервную копию всех входных массивов в Python перед вызовом моей процедуры Fortran. Скомпилируйте подпрограммы Fortran, используя объявление «intent (inplace)» в моей подписи. При выходе я могу восстановить входы с помощью резервной копии.
- Скомпилируйте одну и ту же процедуру Fortran с двумя разными файлами сигнатур, один с «намерением (на месте)», а другой с «намерением (в, вне)» (или просто «намерение (в)», в зависимости от ситуации). Затем в python я могу импортировать обе разновидности подпрограмм в свой модуль.
Мне не очень нравится ни один из подходов, потому что они оба кажутся непитоновскими. Есть ли лучший способ подойти к этой проблеме? Есть ли более простой способ реализовать подход 2, например. Могу ли я скомпилировать одну и ту же процедуру с двумя разными подписями в один общий объектный модуль?
Вот пример (на основе этой документации).
Подпрограмма Fortran fib.f:
C FILE: FIB.F
SUBROUTINE FIB(A,N)
C
C CALCULATE FIRST N FIBONACCI NUMBERS
C
INTEGER N
REAL*8 A(N)
DO I=1,N
IF (I.EQ.1) THEN
A(I) = 0.0D0
ELSEIF (I.EQ.2) THEN
A(I) = 1.0D0
ELSE
A(I) = A(I-1) + A(I-2)
ENDIF
ENDDO
END
C END FILE FIB.F
Я создаю свой файл подписи, используя f2py fib.f -m fib.pyf
, затем добавляю несколько объявлений о намерениях:
! -*- f90 -*-
! Note: the context of this file is case sensitive.
python module fib ! in
interface ! in :fib
subroutine fib(a,n) ! in :fib:fib.f
real*8 dimension(n), intent(inout) :: a
integer, optional,check(len(a)>=n),depend(a) :: n=len(a)
end subroutine fib
end interface
end python module fib
! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/
Я компилирую с помощью f2py -c fib.pyf fib.f
, а затем могу запустить свою процедуру на месте:
>>> import numpy as np
>>> from fib import fib
>>> A = np.zeros(10, dtype=float)
>>> fib(A)
>>> print(A)
[ 0. 1. 1. 2. 3. 5. 8. 13. 21. 34.]
Чтобы изменить этот пример на режим ввода/вывода, я просто изменяю объявление намерения в «fib.pyf» на intent(in,out)
.