Fortran Mex 文件 - 传回 Matlab 的值不正确

Posted

技术标签:

【中文标题】Fortran Mex 文件 - 传回 Matlab 的值不正确【英文标题】:Fortran Mex File - Incorrect Values Passed Back to Matlab 【发布时间】:2014-03-11 01:31:35 【问题描述】:

我在 Fortran 中编写了一个子例程来处理我的代码的计算密集型部分。我想使用 mex 函数将它链接到 Matlab。这是给出相关错误的最简单版本。首先,这是 mex 函数。

#include <fintrf.h>
!======================================================================
#if 0
!     
!     example.F90
!     .F90 file needs to be preprocessed to generate .for equivalent
!     
#endif
!======================================================================
! Matlab command
! deltaHat = example(z)
!----------------------------------------------------------------------
!     Gateway routine
      SUBROUTINE mexFunction(nlhs, plhs, nrhs, prhs)
      IMPLICIT NONE

!     mexFunction arguments:
      MWPOINTER ::  plhs(*), prhs(*)
      INTEGER :: nlhs, nrhs

!     Function declarations:
      mwPointer :: mxGetPr
      mwPointer :: mxCreateDoubleMatrix
      mwSize :: mxGetM, mxGetN

!     Pointers to input/output mxArrays:
      mwPointer :: deltaHat
      mwPointer :: z

!     Array information:
      mwSize :: N

!------------------------------------------------------------------------
!     Get the size of the input array.
      N = mxGetN(prhs(1))

!     Create Fortran arrays from the input argument.
      z = mxGetPr(prhs(1))


!     Create matrix for the return argument.
      plhs(1) = mxCreateDoubleMatrix(1,24,0)
      deltaHat = mxGetPr(plhs(1))

!     Call the computational subroutine. 
      CALL example(%val(deltaHat), %val(z), N)

      END SUBROUTINE

!-----------------------------------------------------------------------
!     Computational routine for contraction mapping


      SUBROUTINE example(deltaHat, z, N)      
      IMPLICIT NONE

      INTEGER, PARAMETER :: dble = selected_real_kind(15)
      INTEGER, PARAMETER :: J = 24

      ! Type delcarations for inputs

      mwSize :: N
      REAL(KIND=dble), DIMENSION(1,J-1), INTENT(OUT) :: deltaHat
      REAL(KIND=dble), DIMENSION(N,1), INTENT(IN) :: z

      ! Declare local variables
      REAL(KIND=dble), DIMENSION(N,J) :: num

      num(:,1) = z(:,1)

      DO i = 1,J-1
        deltaHat(1,i) = num(i,1)
      END DO

      END SUBROUTINE

然后我使用“mex example.F90”在 Matlab 中编译 mex 函数。那里没有问题。现在这是 Matlab 代码和输出。

clear all;

N = 1000;
J = 25;

% Generate covariates-----------------------------------------------------

% Reset random number generators                                
rng('default');

% Create indicators for parameter heterogeneity

z = randi(2,N,1);
z = z-ones(N,1);

deltaHat = example(z);

>> sum(deltaHat' - z(1:J-1))

ans =

    -15

>> deltaHat

deltaHat =

Columns 1 through 11

1.0000    0.0000         0         0    0.0000    0.0000    0.0000    0.0000    0.0000      0.0000    0.0000

Columns 12 through 22

0.0000    0.0000    0.0000    0.0000    0.0000    0.0000    0.0000    0.0000    0.0000    0.0000    0.0000

Columns 23 through 24

0.0000    0.0000

>> z(1:J-1)

ans =

 1
 1
 0
 1
 1
 0
 0
 1
 1
 1
 0
 1
 1
 0
 1
 0
 0
 1
 1
 1
 1
 0
 1
 1

sum(deltaHat' - z(1:J-1)) 项应该为零,因为 deltaHat 和 z(1:J-1) 应该是同一个向量。我还在上面打印了这些向量,以防我丢失了变量类型定义(尽管我已经检查过两者都是双精度的)。显然,数据没有正确地传递给 Fortran 并返回。但是,如果我在 mex 文件中进行以下调整

...
DO i = 1,J-1
   deltaHat(1,i) = z(i,1)
END DO
...

然后我得到正确的答案。这是相应的 Matlab 输出。

...
>> sum(deltaHat' - z(1:J-1))

ans =

     0
...

所以在这种情况下,数据正在从 Matlab 传递到 Fortran 子例程并正确返回。问题似乎在于将 z 分配给 mex 文件中的局部变量 num 。跳过这一步给出正确答案。

【问题讨论】:

您能否提供一个最小的示例代码来显示您在 MATLAB 方面的问题?此外,最好删除与问题无关的所有代码(如 while 循环中注释掉的代码)。展示您的问题的最小但可构建的示例是快速获得答案的最佳方式。 嘿彼得,我已经编辑了我的帖子以使其尽可能简单并且仍然显示错误。感谢您的评论!我觉得现在清楚多了。 z = randi(2,N,1) 在 1,2 中生成随机整数。我希望它们在 0,1 中,所以我只是从 z 中减去一个向量,即 z = z-ones(N,1)。 你试过了吗? dble = selected_real_kind(8) 【参考方案1】:

N 传递给 SUBROUTINE example 是 1。因此,当您分配 deltaHat(1,2) = z(2,1) 时,您正在触及数组 z 的边界

将行 n = mxGetN(prhs(1)) 更改为 n = mxGetM(prhs(1))

你应该学习如何debug your MEX functions,这样你就可以轻松地修复这种琐碎的错误。

【讨论】:

如果它解决了您的问题,请不要忘记接受答案

以上是关于Fortran Mex 文件 - 传回 Matlab 的值不正确的主要内容,如果未能解决你的问题,请参考以下文章

关于MEX函数的说明

用于 Fortran 的 mex 网关中 REAL 变量的可移植声明

在 Windows 上使用 GFortran 在 Matlab 中创建 Mex 文件

如何修复 mex 文件中的非法字符错误

Fortran & Matlab 链接——未定义的符号

Fortran 子程序中的数组分配