【问题标题】:Segmentation fault when calling METIS from FORTRAN [duplicate]从 FORTRAN 调用 METIS 时出现分段错误 [重复]
【发布时间】:2018-08-19 16:49:20
【问题描述】:

我正在开发一个 Fortran 90 程序并将其与 METIS 库链接。我正在使用 GNU Fortran 4.8.5 和 METIS 5.1.0。我编译我的 Fortran 程序:

-fdefault-real-8 -fdefault-integer-8

选项,以及在构建 METIS 时我指定:

#define IDXTYPEWIDTH 64 

#define REALTYPEWIDTH 64 

因此整数和实数的长度都应该合适。当我编译并运行以下程序时:

program Test_Metis
implicit none
integer              :: nvtxs,          &  ! number of vertices
                        ncons,          &  ! number of connections          
                        nparts = 2         ! requested number of partitions
integer, pointer     :: vwgt  =>null(), &  ! weights of the vertices
                        vsize =>null(), &  ! size of the vertices
                        adjwgt=>null(), &  ! weights of the edges
                        mopts =>null(), &  ! array of options
                        objval=>null()     ! stores edgecut or comm. volume
real, pointer        :: tpwgts=>null(), &  ! desired weight for each partition
                        ubvec =>null()     ! 
integer, allocatable :: xadj  (:),      &  ! variabes for ...
                        adjncy(:),      &  ! ... compressed row storage
                        part  (:)          ! partition of the grid

nvtxs = 15
ncons = 22
allocate(xadj  (nvtxs+1))
allocate(adjncy(ncons*2))
allocate(part  (nvtxs))

xadj = (/ 0,  2,  5,  8, 11, 13, 16, 20,  &
         24, 28, 31, 33, 36, 39, 42, 44/)

adjncy=(/ 1,  5,  0,  2,  6,  1,  3,  7,  2,  4,  8,  &
          3,  9,  0,  6, 10,  1,  5,  7, 11,  2,  6,  &
          8, 12,  3,  7,  9, 13,  4,  8, 14,  5, 11,  &
          6, 10, 12,  7, 11, 13,  8, 12, 14,  9, 13/)

call METIS_PartGraphRecursive(nvtxs,     &  ! (in), int
                              ncons,     &  ! (in), int
                              xadj,      &  ! (in), int(:)
                              adjncy,    &  ! (in), int(:)
                              vwgt,      &  ! (in), int(:)
                              vsize,     &  ! (in), int(:)
                              adjwgt,    &  ! (in), int(:)
                              nparts,    &  ! (in), int(:)
                              tpwgts,    &  ! (in), real(:)
                              ubvec,     &  ! (in), real(:)
                              mopts,     &  ! (in), int(:)
                              objval,    &  ! (out) int(:)
                              part)         ! (out) int(:)
end program

我遇到了分段错误。 (我从 METIS 手册中获取了邻接,这应该是非常基本的。)

谁能帮我解决这个问题?

【问题讨论】:

  • 不查看 API 文档:您确定允许将参数(例如 ubvec)作为非关联指针吗?
  • 如果您使用 gfortran 的 -fdefault-* 选项来编译您的代码,那么您需要使用这些选项编译您与您的代码链接的所有库。这些选项破坏了 Fortran 的存储关联规则。如果您不使用这些选项会发生什么。
  • 我倾向于相信this other question 可以解决您的问题。请检查。
  • 亲爱的@francescalus:感谢您的回答。实际上,根据 API 文档,应该为例程未使用的数据发送空指针。我也在那里关注了你的链接和建议。使用 c_iso_binding、c_ptr 和 c_null_ptr 让我更进一步,但并没有解决所有问题。最终,我以 API 和所有工作所需的扩展形式发送所有参数。
  • 亲爱的@evets 感谢您的回答,但我与 -fdefault 选项非常一致。我也非常小心地为浮点数和整数使用相同的长度。

标签: segmentation-fault fortran metis


【解决方案1】:

这是从 Fortran 调用 METIS 所需的最低要求:

program Test_Metis                                                              
use iso_c_binding                                                               
implicit none                                                                   
integer              :: nvtxs  = 15,       &  ! number of vertices              
                        nedgs  = 22,       &  ! number of edges                 
                        ncons  =  1,       &  ! number of constraints           
                        nparts =  2,       &  ! requested number of partitions  
                        objval,            &  ! return value from METIS call    
                        mopts(41)             ! array of options                
type(c_ptr)          :: vwgt  =c_null_ptr, &  ! weights of the vertices         
                        vsize =c_null_ptr, &  ! size of the vertices            
                        adjwgt=c_null_ptr     ! weights of the edges            
real                 :: ubvec                 !                                 
integer, allocatable :: xadj  (:),         &  ! variabes for ...                
                        adjncy(:),         &  ! ... compressed row storage         
                        part  (:)             ! partition of the grid           
real, allocatable    :: tpwgts(:)             ! desired weight for each partition

allocate(xadj  (nvtxs+1))                                                       
allocate(adjncy(nedgs*2))                                                       
allocate(part  (nvtxs))                                                         
allocate(tpwgts(nparts))                                                        

xadj = (/ 0,  2,  5,  8, 11, 13, 16, 20,  &                                     
         24, 28, 31, 33, 36, 39, 42, 44/)                                       
adjncy=(/ 1,  5,  0,  2,  6,  1,  3,  7,  2,  4,  8,  &                         
          3,  9,  0,  6, 10,  1,  5,  7, 11,  2,  6,  &                         
          8, 12,  3,  7,  9, 13,  4,  8, 14,  5, 11,  &                         
          6, 10, 12,  7, 11, 13,  8, 12, 14,  9, 13/)                           

tpwgts(:) =  1.0 / real(nparts)  ! all parts weigh the same                     
ubvec     =  1.001               ! this would be default by METIS anyway        
mopts(:)  = -1                   ! -1 is default value for all options          

call METIS_PartGraphRecursive(nvtxs,     &  ! (in), int                         
                              ncons,     &  ! (in), int                         
                              xadj,      &  ! (in), int(:)                      
                              adjncy,    &  ! (in), int(:)                      
                              vwgt,      &  ! (in), int(:)                      
                              vsize,     &  ! (in), int(:)                      
                              adjwgt,    &  ! (in), int(:)                      
                              nparts,    &  ! (in), int(:)                      
                              tpwgts,    &  ! (in), real(:)                     
                              ubvec,     &  ! (in), real(:)                     
                              mopts,     &  ! (in), int(:)                      
                              objval,    &  ! (out) int(:)                      
                              part)         ! (out) int(:)                      
end program                                                                     

【讨论】:

  • 那么问题出在哪里?这个答案的重点是什么?缺少一些东西,您正在通过引用传递空指针。
  • @VladimirF:我认为至少有两个问题。首先,我将 Fortran 的 null() 用于空指针,这与 C 指针不太一样。然后我介绍了 iso_c_binding 模块,并使用带有 type(c_ptr) 的本机 C 指针并将它们设置为 c_null_ptr。这解决了大多数参数传递的问题,除了“ubvec”和“tpwgts”。无论 METIS API 文档怎么说,这些都不接受指针。我不知道比这更好。
  • @Steve 感谢您的建议 :-)
  • 但是我在这里没有看到METIS_PartGraphRecursive 的任何接口。你是否有一个?无论如何,我几乎倾向于将这个问题作为@francescalus 链接的问题的副本来结束。但请注意,目前您传递的不是 C 指针,而是 C 指针的地址。您不是通过值而是通过引用传递空指针。
  • @VladimirF :你可能有一点;我提出的问题与francescalus 指出的问题没有太大不同。也许关闭它不是一个坏主意。
猜你喜欢
  • 2012-12-14
  • 1970-01-01
  • 2013-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
相关资源
最近更新 更多