很难让OpenMP与f2py一起工作

2024-09-28 15:32:50 发布

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

我正在为我的研究做一些模拟工作,在将fortran导入python脚本时遇到了一个问题。作为背景,我已经与Python一起工作了好几年,只有在需要时才在Fortran内部闲逛。在

我在过去用Fortran实现一些简单的OpenMP功能做了一些工作。我不是这方面的专家,但我以前已经掌握了基本知识。在

我现在使用f2py创建一个可以从python脚本调用的库。当我试图编译openmp时,它可以正确编译并运行到完成,但是速度没有任何提高,看看top,我发现CPU使用率表明只有一个线程在运行。在

我已经搜索了f2py的文档(这不是很好的文档),也做了常规的web搜索以寻找答案。我包括了我正在编译的Fortran代码以及一个调用它的简单python脚本。我还抛出了我正在使用的编译命令。在

目前,我把模拟减少到10^4,作为一个很好的基准。在我的系统上运行需要3秒钟。最后,我需要运行10^6粒子模拟,所以我需要减少一点时间。在

如果有人能给我指出如何让我的代码工作的方向,我将不胜感激。我还可以尝试根据需要包含有关系统的任何详细信息。在

干杯, 里坎


1)编译

f2py -c --f90flags='-fopenmp' -lgomp -m calc_accel_jerk calc_accel_jerk.f90

2)要调用的Python脚本

^{pr2}$

3)Fortran代码

subroutine calc (input_array, nrow, output_array)
implicit none
!f2py threadsafe
include "omp_lib.h"

integer, intent(in) :: nrow
double precision, dimension(nrow,7), intent(in) :: input_array
double precision, dimension(nrow,2), intent(out) :: output_array

! Calculation parameters with set values
double precision,parameter :: psr_M=1.55*1.3267297e20
double precision,parameter :: G_Msun=1.3267297e20
double precision,parameter :: pc_to_m=3.08e16

! Vector declarations
integer :: irow
double precision :: vfac
double precision, dimension(nrow) :: drx,dry,drz,dvx,dvy,dvz,rmag,jfac,az,jz

! Break up the input array for faster access
double precision,dimension(nrow) :: input_M
double precision,dimension(nrow) :: input_rx
double precision,dimension(nrow) :: input_ry
double precision,dimension(nrow) :: input_rz
double precision,dimension(nrow) :: input_vx
double precision,dimension(nrow) :: input_vy
double precision,dimension(nrow) :: input_vz

input_M(:)  = input_array(:,1)*G_Msun
input_rx(:) = input_array(:,2)*pc_to_m
input_ry(:) = input_array(:,3)*pc_to_m
input_rz(:) = input_array(:,4)*pc_to_m
input_vx(:) = input_array(:,5)*1000
input_vy(:) = input_array(:,6)*1000
input_vz(:) = input_array(:,7)*1000

!$OMP PARALLEL DO private(vfac,drx,dry,drz,dvx,dvy,dvz,rmag,jfac,az,jz) shared(output_array) NUM_THREADS(2)
DO irow = 1,nrow
    ! Get the i-th iteration
    vfac  = sqrt(input_M(irow)/psr_M)
    drx   = (input_rx-input_rx(irow))
    dry   = (input_ry-input_ry(irow))
    drz   = (input_rz-input_rz(irow))
    dvx   = (input_vx-input_vx(irow)*vfac)
    dvy   = (input_vy-input_vy(irow)*vfac)
    dvz   = (input_vz-input_vz(irow)*vfac)
    rmag  = sqrt(drx**2+dry**2+drz**2)
    jfac  = -3*drz/(drx**2+dry**2+drz**2)

    ! Calculate the acceleration and jerk
    az = input_M*(drz/rmag**3)
    jz = (input_M/rmag**3)*((dvx*drx*jfac)+(dvy*dry*jfac)+(dvz+dvz*drz*jfac))

    ! Remove bad index
    az(irow) = 0
    jz(irow) = 0

    output_array(irow,1) = sum(az)
    output_array(irow,2) = sum(jz)
END DO
!$OMP END PARALLEL DO

END subroutine calc

Tags: inputoutputarrayprecisiondrydoubledimensionirow
1条回答
网友
1楼 · 发布于 2024-09-28 15:32:50

下面是一个简单的检查,看看OpenMP线程是否确实在Fortran代码中可见:

module OTmod
  !$ use omp_lib
  implicit none

  public :: get_threads

contains

  function get_threads() result(nt)
    integer :: nt

    nt = 0
    !$ nt = omp_get_max_threads()

  end function get_threads

end module OTmod

汇编:

^{pr2}$

执行:

> python
>>> from OTfor import otmod
>>> otmod.get_threads()
12

相关问题 更多 >