Spec-Zone.ru › NumPy 2.0

Использование через meson

Примечание

Большая часть этого документа устарела, можно запустить f2py с --build-dir для получения скелетного проекта meson с базовыми зависимостями.

Изменено в версии 1.26.x: По умолчанию система сборки для f2py теперь meson, см. Состояние numpy.distutils и рекомендации по миграции для получения дополнительной информации.

Ключевое преимущество использования meson по сравнению с методами, описанными в Использование через numpy.distutils, заключается в том, что это позволяет легко интегрироваться в существующие системы и крупные проекты. meson имеет довольно питоновский синтаксис, что делает его более удобным и допускающим расширение для пользователей python.

Прохождение по Fibonacci (F77)

Нам понадобится сгенерированный C обёртки, прежде чем мы сможем использовать общую систему сборки, такую как meson. Мы получим её следующим образом:

python -m numpy.f2py fib1.f -m fib2

Теперь рассмотрим следующий meson.build файл для примеров fib и scalar из раздела Три способа обертки - начало работы:

project('f2py_examples', 'c',
  version : '0.1',
  license: 'BSD-3',
  meson_version: '>=0.64.0',
  default_options : ['warning_level=2'],
)

add_languages('fortran')

py_mod = import('python')
py = py_mod.find_installation(pure: false)
py_dep = py.dependency()

incdir_numpy = run_command(py,
  ['-c', 'import os; os.chdir(".."); import numpy; print(numpy.get_include())'],
  check : true
).stdout().strip()

incdir_f2py = run_command(py,
    ['-c', 'import os; os.chdir(".."); import numpy.f2py; print(numpy.f2py.get_include())'],
    check : true
).stdout().strip()

inc_np = include_directories(incdir_numpy, incdir_f2py)

py.extension_module('fib2',
  [
    'fib1.f',
    'fib2module.c',  # note: this assumes f2py was manually run before!
  ],
  incdir_f2py / 'fortranobject.c',
  include_directories: inc_np,
  dependencies : py_dep,
  install : true
)

На этом этапе сборка завершится, но импорт завершится ошибкой:

meson setup builddir
meson compile -C builddir
cd builddir
python -c 'import fib2'
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: fib2.cpython-39-x86_64-linux-gnu.so: undefined symbol: FIB_
# Check this isn't a false positive
nm -A fib2.cpython-39-x86_64-linux-gnu.so | grep FIB_
fib2.cpython-39-x86_64-linux-gnu.so: U FIB_

Вспомните, что исходный пример, как воспроизведённый ниже, был в стиле SCREAMCASE:

C FILE: FIB1.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 FIB1.F

При стандартном подходе подпрограмма, экспонированная для python, является fib, а не FIB. Это означает, что у нас есть несколько вариантов. Один подход (если это возможно) заключается в приведении исходного файла Fortran к нижнему регистру, например:

tr "[:upper:]" "[:lower:]" < fib1.f > fib1.f
python -m numpy.f2py fib1.f -m fib2
meson --wipe builddir
meson compile -C builddir
cd builddir
python -c 'import fib2'

Однако это требует возможности модифицировать исходный код, что не всегда возможно. Самый простой способ решения этой проблемы — позволить f2py справиться с этим:

python -m numpy.f2py fib1.f -m fib2 --lower
meson --wipe builddir
meson compile -C builddir
cd builddir
python -c 'import fib2'

Автоматизация генерации обёртки

Основной проблемой в описанном выше рабочем процессе является ручная отслеживание входов. Хотя это потребовало бы больше усилий для определения фактических выходов по причинам, обсуждаемым в F2PY и системы сборки.

Примечание

Начиная с NumPy 1.22.4 и далее, f2py будет детерминированно генерировать файлы обёртки на основе стандартного Fortran входного файла (F77 или выше). --skip-empty-wrappers можно передать f2py для восстановления предыдущего поведения, при котором обёртки генерируются только при необходимости для входного файла.

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

project('f2py_examples', 'c',
  version : '0.1',
  license: 'BSD-3',
  meson_version: '>=0.64.0',
  default_options : ['warning_level=2'],
)

add_languages('fortran')

py_mod = import('python')
py = py_mod.find_installation(pure: false)
py_dep = py.dependency()

incdir_numpy = run_command(py,
  ['-c', 'import os; os.chdir(".."); import numpy; print(numpy.get_include())'],
  check : true
).stdout().strip()

incdir_f2py = run_command(py,
    ['-c', 'import os; os.chdir(".."); import numpy.f2py; print(numpy.f2py.get_include())'],
    check : true
).stdout().strip()

fibby_source = custom_target('fibbymodule.c',
  input : ['fib1.f'],  # .f so no F90 wrappers
  output : ['fibbymodule.c', 'fibby-f2pywrappers.f'],
  command : [py, '-m', 'numpy.f2py', '@INPUT@', '-m', 'fibby', '--lower']
)

inc_np = include_directories(incdir_numpy, incdir_f2py)

py.extension_module('fibby',
  ['fib1.f', fibby_source],
  incdir_f2py / 'fortranobject.c',
  include_directories: inc_np,
  dependencies : py_dep,
  install : true
)

Это можно скомпилировать и запустить как раньше.

rm -rf builddir
meson setup builddir
meson compile -C builddir
cd builddir
python -c "import numpy as np; import fibby; a = np.zeros(9); fibby.fib(a); print (a)"
# [ 0.  1.  1.  2.  3.  5.  8. 13. 21.]

Основные моменты

Стоит учитывать следующее:

  • В данном контексте использовать SCREAMCASE невозможно, поэтому содержимое файла .f или сгенерированная обёртка .c должна быть приведена к нижнему регистру; что можно сделать с помощью параметра --lower F2PY

© 2005–2024 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/2.0/f2py/buildtools/meson.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API