我试图写一个做一些矩阵乘法的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中更有效吗?