【问题标题】:Using f2py for faster calculation on Python使用 f2py 在 Python 上进行更快的计算
【发布时间】:2020-11-19 06:58:21
【问题描述】:

我正在用python做一个序列比对项目,python for循环太慢了。

所以,我决定使用f2py。我对fortran不太了解,所以我坚持以下几点。

有两个序列名为'column'和'row',其类型为np.array

例如:

column = ['A', 'T', 'G', 'C']
row = ['A', 'A', 'C', 'C'] 

我为Needleman-Wunsch 算法创建了一个矩阵,并对两个序列(列、行)进行了评分。

    import numpy as np
    column = np.array(list('ATGC'))
    row = np.array(list('AACC'))
    matrix = np.zeros((len(column) + 1, len(row) + 1), dtype='int')

    for i in range(1, len(column)+1):
        self.matrix[i][0] = -1 * i

    for j in range(1, len(row)+1):
        self.matrix[0][j] = -1 * j

    matchCheck = 0

    for i in range(1, len(column) + 1):
        for j in range(1, len(row) + 1):
            if column[i-1] == row[j-1]:
                matchCheck = 1 
            else:
                matchCheck = -1 
            top = matrix[i-1][j] + -1
            left = matrix[i][j-1] + -1
            top_left = matrix[i-1][j-1] + matchCheck
            matrix[i][j] = max(top, left, top_left)

我想从 fortran 获得一些帮助以加快计算速度,所以我用 fortran 编写了一个代码。

subroutine needlemanWunsch(matrix, column, row, cc, rr, new_matrix)
integer, intent(in) :: cc, rr
character, intent(in) :: column(0:cc-1), row(0:rr-1)
integer, intent(in) :: matrix(0:cc, 0:rr)
integer, intent(out) :: new_matrix(0:cc, 0:rr)
integer :: matchcheck, top, left, top_left

do i = 1, cc
    new_matrix(i, 0) = -1 * i
end do

do j = 1, rr
    new_matrix(i, 0) = -1 * j
end do

do k = 1, cc
    do l = 1, rr
        if (column(i-1).EQ.row(j-1)) then
            matchcheck = 1
        else
            matchcheck = -1 
        
        top = matrix(i-1, j) + inDel
        left = matrix(i, j-1) + inDel
        top_left = matrix(i-1, j-1) + matchCheck
        new_matrix(i, j) = max(top, left, top_left)
        end if 
    end do
end do 
return
end subroutine

然后,我用 f2py 转换了这个 fortran 代码,并用这个代码将它导入到 python 上。

    import numpy as np
    column = np.array(list('ATGC'))
    row = np.array(list('AACC'))
    matrix = np.zeros((len(column) + 1, len(row) + 1), dtype='int')
    
    # import my fortran code 
    matrix = algorithm.needlemanwunsch(matrix, column, row, cc, rr)

每当我尝试导入 fortran 代码时
它崩溃了......

【问题讨论】:

  • 你究竟是如何使用fortran子程序的?请提供一个最小的工作示例。
  • 我做到了。谢谢
  • 它仍然不是自我功能:self 是什么?请提供minimal working example。你能不能只删除self 部分作为一个最小的例子?
  • 将其更改为自功能。这是我第一次访问这个网站。谢谢你的建议。
  • 在您的 fortran 中,您似乎在设置值之前使用 inDel。另外,您确定您的 endif 在 Fortran 中的正确位置吗?我对 python 的了解非常粗略,但我会认为这两个代码在我看来是不同的,如果在 fortran 中结束,是否应该在 matchcheck = -1 之后?

标签: python fortran f2py


【解决方案1】:

以下在我的情况下有效。

文件neeldemanWunsch.f90

subroutine needlemanWunsch(matrix, column, row, cc, rr, new_matrix)
  integer, intent(in) :: cc, rr
  character, intent(in) :: column(0:cc-1), row(0:rr-1)
  integer, intent(in) :: matrix(0:cc, 0:rr)
  integer, intent(out) :: new_matrix(0:cc, 0:rr)
  integer :: matchcheck, top, left, top_left

  do i = 1, cc
      new_matrix(i, 0) = -1 * i
  end do

  do j = 1, rr
      new_matrix(i, 0) = -1 * j
  end do

  do k = 1, cc
      do l = 1, rr
          if (column(i-1).EQ.row(j-1)) then
              matchcheck = 1
          else
              matchcheck = -1

          top = matrix(i-1, j) + inDel
          left = matrix(i, j-1) + inDel
          top_left = matrix(i-1, j-1) + matchCheck
          new_matrix(i, j) = max(top, left, top_left)
          end if
      end do
  end do
  return
end subroutine

通过f2py编译

$ f2py -c needlemanWunsch.f90 -m needlemanWunsch

导入python文件needlemanWunsch.py。 这就是您的错误的来源! 您需要导入已编译的模块,请参见下面的示例。

import needlemanWunsch         # THIS IS MISSING IN YOUR CODE!!
import numpy as np

# create matrix
_column = ['A', 'T', 'G', 'C']
_row = ['A', 'A', 'C', 'C']
column = np.array(list(_column))
row = np.array(list(_row))
cc = len(column)
rr = len(column)
matrix = np.zeros((len(column) + 1, len(row) + 1), dtype='int')

# import my fortran code
matrix = needlemanWunsch.needlemanwunsch(matrix, column, row, cc, rr)

print(matrix)

输出是

$ python needlemanWunsch.py 
[[ 0 -4  0  0  0]
 [-1  0  0  0  0]
 [-2  0  0  0  0]
 [-3  0  0  0  0]
 [-4  0  0  0  0]]

【讨论】:

  • 它可能会编译并运行,但它会产生合理的输出吗? Fortran 循环索引kl 没有被使用(只是重复使用ij 的最后一个值?),inDel 使用未定义。
  • 主要问题是如何通过 f2py 访问 python 中的 fortran 子例程,我希望我展示了如何做到这一点。如果 fortran 例程真的有意义或没有意义,那就是完全不同的故事了..
  • j 上的第二个 do-loop 一定是错误的。您正在初始化相同的 new_matrix(i,0) 元素,这将踩到错误的内存位置。
  • @evets 正如我之前所说:这里不关心实际过程,因为问题是如何通过 python 中的 f2py 调用此子例程(或任何其他例程)。 (我刚刚从问题中复制了这个示例过程 1to1...)
  • @jack,为了 OP 的利益,我只是指出 do j=1, rr; new_matrix(i,0) = -1*j; end do 不可能是正确的。特别是如果cc 大于rr,则new_matrix(i,0) 正在引用超出其边界的数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-27
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 2014-05-20
相关资源
最近更新 更多