传递布尔数组而不使用“f2py”进行复制?

2024-10-01 15:34:07 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我打算给Fortran变量传递一个带有f2py的布尔型NumPy数组,那么应该如何对Fortran变量进行类型化?我尝试过integer*1logical*1,但这两个都表明数组被复制了。在

例如,如果我编译文件foo.f95,其中包含:

subroutine foo(x, n)
    logical*1 x(n)
    !f2py intent(in) x
    !f2py intent(hide), depend(x) :: n=shape(x,0)
    ...
end subroutine

使用f2py -c -m foo foo.f90 -DF2PY_REPORT_ON_ARRAY_COPY=1并运行类似于:

^{pr2}$

它印出来了

copied an array: size=100, elsize=1

如果将logical*1更改为integer*1,则得到相同的结果。Fortran文件中布尔数组的正确类型是什么,以便不复制该数组?在

注意,这不是内存连续性的问题,因为数组是1D的--foo.foo(np.asfortranarray(x))打印相同的复制消息。在


Tags: 文件innumpyfoointeger数组hidefortran
1条回答
网友
1楼 · 发布于 2024-10-01 15:34:07

从一些实验(*),Python/f2py似乎认为np.int8与{}兼容,而{}或{}不是出于某种原因。在将print *, "(fort) x = ", x插入foo.f90后,我们得到:

>>> foo.foo( np.array( [ True, False, False ], dtype=np.bool ) )
copied an array: size=3, elsize=1
 (fort) x =  T F F
>>> foo.foo( np.array( [ False, True, False ], dtype=np.bool8 ) )
copied an array: size=3, elsize=1
 (fort) x =  F T F
>>> foo.foo( np.array( [ False, False, True ], dtype=np.int8 ) ) # no copy
 (fort) x =  F F T

因为True和{}只是映射到1和0,所以在Python端使用int8数组可能比较方便。在


(*)一些实验

在这里,我将f2py意图注释改为inout,看看我们是否可以从Fortran端修改数组。在

食品f90:

^{pr2}$

在测试.py公司名称:

import numpy as np
import foo

for T in [ np.bool, np.bool8,
           np.int,  np.int8,  np.int32,  np.int64,
           np.uint, np.uint8, np.uint32, np.uint64,
           np.dtype('b'), np.dtype('int8'), np.dtype('int32') ]:

    print( "            -" )
    print( "dtype =", T )

    x = np.array( [ True, False, True ], dtype=T )
    print( "input x =", x )

    try:
        foo.foo( x )
        print( "output x =", x )
    except:
        print( "failed" )

logical*1的结果:

            -
dtype = <class 'bool'>
input x = [ True False  True]
failed
            -
dtype = <class 'numpy.bool_'>
input x = [ True False  True]
failed
            -
dtype = <class 'int'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.int8'>
input x = [1 0 1]
 (fort) x =  T F T
 (fort) sizeof(x(1)) =                     1
 (fort) resetting x(:) to true
output x = [1 1 1]
            -
dtype = <class 'numpy.int32'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.int64'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.uint64'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.uint8'>
input x = [1 0 1]
 (fort) x =  T F T
 (fort) sizeof(x(1)) =                     1
 (fort) resetting x(:) to true
output x = [1 1 1]
            -
dtype = <class 'numpy.uint32'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.uint64'>
input x = [1 0 1]
failed
            -
dtype = int8
input x = [1 0 1]
 (fort) x =  T F T
 (fort) sizeof(x(1)) =                     1
 (fort) resetting x(:) to true
output x = [1 1 1]
            -
dtype = int8
input x = [1 0 1]
 (fort) x =  T F T
 (fort) sizeof(x(1)) =                     1
 (fort) resetting x(:) to true
output x = [1 1 1]
            -
dtype = int32
input x = [1 0 1]
failed

带有logical(默认类型)的结果:

            -
dtype = <class 'bool'>
input x = [ True False  True]
failed
            -
dtype = <class 'numpy.bool_'>
input x = [ True False  True]
failed
            -
dtype = <class 'int'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.int8'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.int32'>
input x = [1 0 1]
 (fort) x =  T F T
 (fort) sizeof(x(1)) =                     4
 (fort) resetting x(:) to true
output x = [1 1 1]
            -
dtype = <class 'numpy.int64'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.uint64'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.uint8'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.uint32'>
input x = [1 0 1]
 (fort) x =  T F T
 (fort) sizeof(x(1)) =                     4
 (fort) resetting x(:) to true
output x = [1 1 1]
            -
dtype = <class 'numpy.uint64'>
input x = [1 0 1]
failed
            -
dtype = int8
input x = [1 0 1]
failed
            -
dtype = int8
input x = [1 0 1]
failed
            -
dtype = int32
input x = [1 0 1]
 (fort) x =  T F T
 (fort) sizeof(x(1)) =                     4
 (fort) resetting x(:) to true
output x = [1 1 1]

logical(c_bool)(通过iso\u结合)的结果:

            -
dtype = <class 'bool'>
input x = [ True False  True]
failed
            -
dtype = <class 'numpy.bool_'>
input x = [ True False  True]
failed
            -
dtype = <class 'int'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.int8'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.int32'>
input x = [1 0 1]
 (fort) x =  T F F
 (fort) sizeof(x(1)) =                     1
 (fort) resetting x(:) to true
output x = [65793     0     1]
            -
dtype = <class 'numpy.int64'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.uint64'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.uint8'>
input x = [1 0 1]
failed
            -
dtype = <class 'numpy.uint32'>
input x = [1 0 1]
 (fort) x =  T F F
 (fort) sizeof(x(1)) =                     1
 (fort) resetting x(:) to true
output x = [65793     0     1]
            -
dtype = <class 'numpy.uint64'>
input x = [1 0 1]
failed
            -
dtype = int8
input x = [1 0 1]
failed
            -
dtype = int8
input x = [1 0 1]
failed
            -
dtype = int32
input x = [1 0 1]
 (fort) x =  T F F
 (fort) sizeof(x(1)) =                     1
 (fort) resetting x(:) to true
output x = [65793     0     1]

由于某些原因,最后一个logical(c_bool)不能与上述用法一起使用。。。(f2py似乎认为logical(c_bool)为4个字节,而gfortran将其视为1个字节,因此有些不一致…)

相关问题 更多 >

    热门问题