首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Matlab上增加Mex的文件大小

在Matlab上增加Mex的文件大小
EN

Stack Overflow用户
提问于 2021-02-09 11:18:10
回答 1查看 145关注 0票数 0

我正在用Matlab r2019a编写FORTRAN文件。我用小数组测试了代码,一切都很好。但是,当我试图增加数组的大小时,会出现以下错误。

致命错误LNK1248:图像大小(9B993000)超过最大允许大小(80000000)

我在windows 10上使用VisualStudio2017和英特尔FORTRAN编译器,我有16 got的RAM。这个链接似乎有解决方案,但我似乎找不到链接器选项在VS 2017通过堆数组。

https://software.intel.com/content/www/us/en/develop/articles/intel-fortran-compiler-increased-stack-usage-of-80-or-higher-compilers-causes-segmentation-fault.html

有谁能给我介绍一下如何扩大尺寸?

谢谢基南

代码语言:javascript
复制
    #include "fintrf.h"
C     Gateway routine
      subroutine mexFunction(nlhs, plhs, nrhs, prhs)
       
       

C     Declarations
      implicit none



C     mexFunction arguments:
      mwPointer plhs(*), prhs(*)
      mwSize  nlhs, nrhs


C     Function declarations:
      mwPointer mxCreateDoubleMatrix
      mwPointer mxDuplicateArray

      mwPointer mxGetPr

      mwPointer mxGetM, mxGetN
      mwSize  mxIsNumeric 


C     Pointers to input/output mxArrays:
      mwPointer coord_pr,dualnumfam_pr,dualfail_pr,dualpointfam_pr
      mwPointer dualnodefam_pr,totnode_pr,width_pr,scr0_pr,vol_pr,bc_pr
      mwPointer disp_pr,numfam_pr,nodefam_pr,pointfam_pr,fail_pr
      mwPointer dmgpar1_pr,dmgpar2_pr, pforce_pr, dualpforce_pr
      mwPointer fails_pr,dualfails_pr


C     Array information:
      mwPointer m, n, x, y, u, l,o, p
      mwSize  mm, nn
      mwSize size, row, sizes
      
C     Arguments for computational routine:
      real*8  coord(450000), dualnumfam(300000) 
      real*8 dualfail(30000000), dualpointfam(150000) 
      real*8  dualnodefam(30000000),totnode(1) ,width(1)
      real*8 scr0(150000), vol(150000), bc(150000)
      real*8  disp(450000), numfam(150000),nodefam(30000000) 
      real*8  pointfam(150000),fail(30000000) 
      real*8  dmgpar1(150000),dmgpar2(150000)
      real*8  pforce(450000),dualpforce(450000)
      real*8  fails(30000000),dualfails(30000000)

        
      character*200 msg
      character*20  fmt
      character*10  sm, sn, sx, sy, so, sp
C-----------------------------------------------------------------------
    

C     Check for proper number of arguments. 
      if (nrhs .ne. 15) then
         call mexErrMsgIdAndTxt ('MATLAB:test:nInput',
     +                           'One inputs required.')
      endif

C     Validate inputs
C     Check to see both inputs are numeric.
      if (mxIsNumeric(prhs(1)) .ne. 1) then
         call mexErrMsgIdAndTxt ('MATLAB:test:NonNumeric1',
     +                           'Input # 1 is not a numeric.')
      endif







C     Check that input #1 is a scalar.
      m = mxGetM(prhs(1))
      n = mxGetN(prhs(1))
      size = m*n
      x = mxGetM(prhs(3))
      y = mxGetN(prhs(3))
        sizes=x*y
      u = mxGetM(prhs(5))


      fmt = '(I8)'
      write (sm,fmt) m
      write (sn,fmt) n
      write (sx,fmt) x
      write (sy,fmt) y
       
      msg = 'm=' // trim(sm) // ',\t n=' // trim(sn) // '\n'
      call mexPrintf(trim(msg))
      msg = 'x=' // trim(sx) // ',\t y=' // trim(sy) // '\n'
      call mexPrintf(trim(msg))

C     Create matrix for the return argument.
               call mexPrintf("one")

      plhs(1) = mxCreateDoubleMatrix(m,1,0)
      plhs(2) = mxCreateDoubleMatrix(m,1,0)
      plhs(3) = mxCreateDoubleMatrix(m,3,0)
      plhs(4) = mxCreateDoubleMatrix(m,3,0)
      plhs(5) = mxCreateDoubleMatrix(x,y,0)
      plhs(6) = mxCreateDoubleMatrix(x,y,0)
               call mexPrintf("two")


      coord_pr = mxGetPr(prhs(1))
      dualnumfam_pr = mxGetPr(prhs(2))
      dualfail_pr = mxGetPr(prhs(3))
      dualpointfam_pr = mxGetPr(prhs(4))
      dualnodefam_pr = mxGetPr(prhs(5))
      totnode_pr = mxGetPr(prhs(6))
      width_pr = mxGetPr(prhs(7))
      scr0_pr = mxGetPr(prhs(8))
      vol_pr = mxGetPr(prhs(9))
      bc_pr = mxGetPr(prhs(10))
      disp_pr = mxGetPr(prhs(11))
      numfam_pr = mxGetPr(prhs(12))
      nodefam_pr = mxGetPr(prhs(13))
      pointfam_pr = mxGetPr(prhs(14))
      fail_pr = mxGetPr(prhs(15))
      dmgpar1_pr = mxGetPr(plhs(1))
      dmgpar2_pr = mxGetPr(plhs(2))
      pforce_pr = mxGetPr(plhs(3))
      dualpforce_pr = mxGetPr(plhs(4))
      fails_pr = mxGetPr(plhs(5))
      dualfails_pr = mxGetPr(plhs(6))


               call mexPrintf("three")


C     Load the data into Fortran arrays.
      call mxCopyPtrToReal8(coord_pr,coord,size)    
      call mxCopyPtrToReal8(dualnumfam_pr,dualnumfam,m)
      call mxCopyPtrToReal8(dualfail_pr,dualfail,sizes)
      call mxCopyPtrToReal8(dualpointfam_pr,dualpointfam,m)
      call mxCopyPtrToReal8(dualnodefam_pr,dualnodefam,u)
      call mxCopyPtrToReal8(totnode_pr,totnode,1)
      call mxCopyPtrToReal8(width_pr,width,1)
      call mxCopyPtrToReal8(scr0_pr,scr0,m)
      call mxCopyPtrToReal8(vol_pr,vol,m)
      call mxCopyPtrToReal8(bc_pr,bc,m)
      call mxCopyPtrToReal8(disp_pr,disp,size)
      call mxCopyPtrToReal8(numfam_pr,numfam,m)
      call mxCopyPtrToReal8(nodefam_pr,nodefam,u)
      call mxCopyPtrToReal8(pointfam_pr,pointfam,m)
      call mxCopyPtrToReal8(fail_pr,fail,sizes)
      call mxCopyPtrToReal8(dmgpar1_pr,dmgpar1,m)
      call mxCopyPtrToReal8(dmgpar2_pr,dmgpar2,m)
      call mxCopyPtrToReal8(pforce_pr,pforce,size)
      call mxCopyPtrToReal8(dualpforce_pr,dualpforce,size)
               call mexPrintf("four")

      call mxCopyPtrToReal8(fails_pr,fails,sizes)
      call mxCopyPtrToReal8(dualfails_pr,dualfails,sizes)



C     Call the computational subroutine.
        
      call body(coord,dualnumfam,dualfail,dualpointfam,dualnodefam,
     + totnode,width,scr0,vol,bc,disp,numfam,nodefam,pointfam,fail
     + ,m,n,dmgpar1,dmgpar2,pforce,dualpforce,u,fails,dualfails)
C     Load the output into a MATLAB array.
      call mxCopyReal8ToPtr(dmgpar1,dmgpar1_pr,m)
      call mxCopyReal8ToPtr(dmgpar2,dmgpar2_pr,m)
      call mxCopyReal8ToPtr(pforce,pforce_pr,size)
      call mxCopyReal8ToPtr(dualpforce,dualpforce_pr,size)
      call mxCopyReal8ToPtr(fails,fails_pr,sizes)
      call mxCopyReal8ToPtr(dualfails,dualfails_pr,sizes)


      return
      end
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-10 20:03:14

与堆相比,堆栈的内存相对较少。堆栈是一个固定数量的内存,本质上是程序的一部分。它用于在例程之间传递参数、局部变量内存等。由于其相对较小的大小,不应该创建可能溢出堆栈的大型局部变量。这在任何语言中都是正确的,而不仅仅是Fortran。因此,创建这样的局部变量:

代码语言:javascript
复制
real*8 dualfail(30000000)

导致双失败内存从堆栈中来。

大变量的一种更好的方法是从堆中为它们分配内存,堆基本上是整个计算机内存。例如,

代码语言:javascript
复制
real*8, allocatable :: dualfail(:)
integer alloc_stat
allocate(dualfail(30000000),stat=alloc_stat)
if( alloc_stat /= 0 ) then
    ! allocation failed, so take action here
endif
! code to use dualfail here
deallocate(dualfail)

您的所有大型变量都应该使用此技术。

尽管如此,看来在mex例程中有这些大变量的唯一原因是复制MATLAB输入和输出,用于body( )例程。这是一种非常低效的管理方法。您还在深入复制仅为0的输出变量,尽管我猜它们无论如何都会被body( )覆盖。与其采用这种方法,尤其是在处理大型变量时,最好将“指针”传递到内存到您的例程。其中一种方法是使用%VAL( )构造。这将消除首先创建这些大型局部变量的需要。例如,

代码语言:javascript
复制
  call body(%VAL(coord_pr),%VAL(dualnumfam_pr),%VAL(dualfail_pr), etc.

因此,无论您在哪里传递MATLAB变量数据的副本,您都会将“指针”(实际上将整数中包含的地址按值传递)传递给MATLAB变量的原始数据区域。只要您的body( )例程将MATLAB prhs( )输入作为只读处理,这就不会像您所做的那样需要进行深度复制。这消除了对所有这些mxCopyReal8ToPtr( )和mxCopyPtrToReal8( )调用的需求。

请注意,我上面使用的“指针”一词是泛指的.这些不是Fortran指针变量。但使用实际的Fortran指针将是另一种避免深度数据复制的方法.也就是说,将mxGetPr( )返回的整数转换为正规的Fortran指针,然后在代码中使用该指针。

我还要指出,您的mex例程严重缺乏输入参数检查。您只检查输入的数量,并且第一个输入是数字的。你应该做的是检查你的每一个输入都是双倍的,非复杂的,不稀疏的,并且有正确的大小。因为它的例行是不健全的,你有风险得到错误的结果或崩溃的MATLAB,如果输入不是完全按照预期。

最后,请注意,出于某种原因,Mathworks选择将/fixed选项硬编码到他们的Fortran构建文件中。我已经要求他们删除这个,但是到了R2020a的时候,它还在那里。这迫使编译器将所有文件视为固定格式,甚至是以.f90结尾的文件。我的建议是在系统上找到那些xml文件,并从这些文件中删除/fixed选项。这样,您就可以自然地将.f90文件编译为空闲格式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66117964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档