编写要在R中调用的Fortran矩阵乘法子程序

时间:2015-07-23 13:37:09

标签: r fortran

我试图写一个做一些矩阵乘法的Fortran子程序。我使用R来创建输入:

set.seed(7232015)
#############
# meta data #
#############
B <- 200  # (actually millions)
D <- 100  # number of markov chain monte carlo draws (actually 4,000)
T <- 8    # number of quarters

#########
# input #
#########
input <- data.frame(
    treat = sample(0:1, B, T), # treatment indicator
    time = sample(1:T, B, T),  # time
    weight = rnorm(B),         # weight
    pred = rnorm(B),           # predictions (x \hat\beta)
    eresid = exp(rnorm(B))
)    # exp(resid) exp(y - x \hat\beta)

thetaTime <- matrix(rnorm(T * D), T, D) # time-by-treatment intrxn
theta <-
    thetaTime[input$time,]       # pull off the relevant value for ea obs
rm(list=setdiff(ls(), c("input", "theta", "T")))

我有一个可以满足我需要的R功能:

test2 <- function(d, DF, theta, T){
    D <- ncol(theta)
    B <- nrow(DF)
    DF$epredC <- exp(DF$pred + theta[,d] * (DF$treat == 1))
    DF$epredT <- exp(DF$pred - theta[,d] * (DF$treat == 0))
    DF$diff <-
        as.vector(
            DF$eresid %*% matrix(
                DF$epredT, nrow = B, ncol = B, byrow = T
            )
        )
    return(DF$diff)
}
x <- test2(d = 1, DF = input, theta = theta, T = T)

在本例中,Fortran子程序应该创建大小为200的向量x。

这是我写的fortran代码:

subroutine test3(d, i, nMCd, DF, theta, C)
    integer, intent(in)                                 :: d, i, nMCd
    double precision, intent(in), dimension(i,5)        :: DF
    double precision, intent(in), dimension(i,nMCd)     :: theta
    double precision, dimension(i)                      :: epredC, epredT
    double precision, intent(out), dimension(i)         :: C

    C=0.0d0
    epredC = exp(DF(:,4) + (theta(:,d) * DF(:,1)))
    epredT = exp(DF(:,4) + (theta(:,d) * (1-DF(:,1))))

    do jj=1, i
        do j=1, i
            C(jj) = C(jj) + DF(j,5)*epredT(jj)
        end do
    end do

end subroutine test3 

我能够编译它并在R

上运行它
system("R CMD SHLIB ./Fortran/mytest.f90")
dyn.load("./Fortran/mytest.so")
X <- .Fortran("test3", d = as.integer(1), i = nrow(input), 
              nMCd = nrow(theta), DF = unlist(input), 
              theta = unlist(theta), 
              C = numeric(nrow(input)))

但是在R x[1]=415.937和Fortran X$C[1]=10414.94

我做错了什么?谢谢!

我知道我的循环是错误的,但我无法弄清楚为什么......

如果我将我的fortran子程序改为此,它可以正常工作

subroutine test5(d, i, nMCd, DF, theta, C)
    integer, intent(in)                                 :: d, i, nMCd
    double precision, intent(in), dimension(i,5)        :: DF
    double precision, intent(in), dimension(i,nMCd)     :: theta
    double precision, dimension(i)                      :: epredC, epredT
    double precision, intent(out), dimension(i)         :: C
    double precision, dimension(i,i)                    :: B

    C=0.0d0
    B=0.0d0

    epredC = exp(DF(:,4) + (theta(:,d) * DF(:,1)))
    epredT = exp(DF(:,4) + (theta(:,d) * (1-DF(:,1))))

    do j=1,i
        B(:,j)=epredT(j)
    end do

    C = matmul(DF(:,5), B)

end subroutine test5 

这种方法或循环在Fortran中更有效吗?

0 个答案:

没有答案