我正在Fortran中编写一个简单的矩阵向量乘法程序。在这个程序中,我正在使用cuBLAS的Fortran Binding例程解释here。当我的数组包含少于90个元素时,该程序就像一个魅力。我已经阅读了其他一些建议使用ulimit -s unlimited
或-heap-array [size]
的帖子,但这些帖子在我的案例中并不起作用。还有另一种解决这个问题的方法,我不知道吗?我正在使用ifort和gfortran进行编译,使用nvcc来编译cublas例程。
ifort
$ifort -heap-arrays 1 -names uppercase -assume nounderscore -c -o cublasf.o main.f90
$nvcc -c -DCUBLAS_INTEL_FORTRAN -I/usr/local/cuda/include -I/usr/local/cuda/src -o fortran.o /usr/local/cuda/src/fortran.c
$ifort -heap-arrays 1 -o cublasf fortran.o cublasf.o -L/usr/local/cuda/lib64 -lcublas
gfortran
$gfortran -c -o cublasf.o main.f90
$nvcc -c -DCUBLAS_GFORTRAN -I/usr/local/cuda/include -I/usr/local/cuda/src -o fortran.o /usr/local/cuda/src/fortran.c
$gfortran -o cublasf cublasf.o fortran.o -L/usr/local/cuda/lib64 -lcublas
非常感谢任何帮助。提前谢谢!
以下是我尝试运行的代码。我知道它不是最漂亮的代码,我可以做一些优化,但它仅用于测试。有一些元素被注释掉,仅用于测试目的(无需担心这些)。
main.f90时
program main
implicit none
INTEGER CUBLAS_INIT
INTEGER CUBLAS_ALLOC
INTEGER CUBLAS_FREE
INTEGER CUBLAS_SET_VECTOR
INTEGER CUBLAS_SET_MATRIX
INTEGER CUBLAS_GET_VECTOR
INTEGER CUBLAS_SGEMV
EXTERNAL CUBLAS_SGEMV
INTEGER CUBLAS_SHUTDOWN
integer :: countNumCuda, countNumCuda2,countNumFort,countNumFort2
integer :: clockRate = 4
integer*4, parameter :: N=80
real*4, dimension(N,N) :: mat
real*8 :: devPtr_mat, devPtr_vect, devPtr_outVect
real*4, dimension(N) :: vect,outVect,outVect2, anotherVect
integer :: i,j
integer :: size_of_real = 8
character :: trans = "N"
real*4 :: alpha = 1.0
real*4 :: beta = 0.0
integer :: cublas_status
! Initialize matrix and array
do i = 1, N
do j = 1, N
mat(i,j) = i
end do
vect(i) = i
outVect(i) = 0
outVect2(i) = 0
end do
!call SYSTEM_CLOCK(countNumFort, clockRate)
!call MATRIXVECTORMULT(mat, vect, outVect, N)
!call SYSTEM_CLOCK(countNumFort2, clockRate)
!do i = 1, N
! anotherVect(i) = outVect(i)
!enddo
call SYSTEM_CLOCK(countNumCuda, clockRate)
print*,"Entering GPU"
cublas_status = CUBLAS_INIT()
if (cublas_status .NE. 0) then
print *, "initialization error"
end if
cublas_status = CUBLAS_ALLOC(N*N,size_of_real, devPtr_mat)
if (cublas_status .NE. 0) then
print *, "Allocation error devMat"
end if
cublas_status = CUBLAS_ALLOC(N, size_of_real, devPtr_vect)
if (cublas_status .NE. 0) then
print *, "Allcoation error devVect"
end if
cublas_status = CUBLAS_ALLOC(N, size_of_real, devPtr_outVect)
if (cublas_status .NE. 0) then
print *, "Allocation error devPtrOut"
end if
cublas_status = CUBLAS_SET_VECTOR(N, size_of_real, vect, 1, devPtr_vect, 1)
if (cublas_status .NE. 0) then
print *, "Set vector error", cublas_status
end if
cublas_status = CUBLAS_SET_MATRIX(N,N,size_of_real, mat, N, devPtr_mat, N)
if (cublas_status .NE. 0) then
print *, "Set matrix error", cublas_status
end if
cublas_status = CUBLAS_SGEMV(trans,N,N,alpha, devPtr_mat, N, devPtr_vect,1,beta,devPtr_outVect,1)
if (cublas_status .NE. 0) then
print *, "SGEMV error", cublas_status
end if
cublas_status = CUBLAS_GET_VECTOR(N,size_of_real, devPtr_outVect, 1, outVect2, 1)
if (cublas_status .NE. 0) then
print *, "Get vector error", cublas_status
end if
cublas_status = CUBLAS_FREE(devPtr_mat)
if (cublas_status .NE. 0) then
print *, "free mat error", cublas_status
end if
cublas_status = CUBLAS_FREE(devPtr_vect)
if (cublas_status .NE. 0) then
print *, "free vect error", cublas_status
end if
cublas_status = CUBLAS_FREE(devPtr_outVect)
if (cublas_status .NE. 0) then
print *, "Free outVect error", cublas_status
end if
cublas_status = CUBLAS_SHUTDOWN()
if (cublas_status .NE. 0) then
print *, "shutdown error", cublas_status
end if
call SYSTEM_CLOCK(countNumCuda2, clockRate)
!Results from CUDA
!do i = 1, N
! print *, anotherVect(i), outVect(i), outVect2(i)
!end do
do i = 1, N
print*, outVect2(i)
enddo
!print *, countNumCuda2 - countNumCuda, "Cuda Rate"
!print *, countNumFort2 - countNumFort, "Fortran Rate"
end program main
再次感谢!
答案 0 :(得分:3)
分段错误是由主机代码或访问驻留在主机上的变量引起的。当您在此处寻求有关seg故障的帮助时,最好确定生成seg故障的实际代码行或短代码。使用像这样的简短代码来完成这项工作是一件微不足道的事情,只需在代码中自由地放置印刷语句,看看哪些发生了,哪些不发生。
您的seg故障是由于您将大部分基于主机的存储分配为4字节实数:
real*4, dimension(N,N) :: mat
...
real*4, dimension(N) :: vect,outVect,outVect2, anotherVect
但是当你试图将它们复制到设备时,你正在指示cublas假设每个元素是一个8字节的数量:
integer :: size_of_real = 8
对我来说,这段代码发生了seg错误:
cublas_status = CUBLAS_SET_MATRIX(N,N,size_of_real, mat, N, devPtr_mat, N)
此行指示cublas
将变量mat
复制到设备。但是你要求它复制N * N * 8个字节,这是你的分配的两倍。由于复制例程超出了mat
的分配范围,因此会发生seg错误(最终)。
更改声明以指示每个实际8个字节:
real*8, dimension(N,N) :: mat
...
real*8, dimension(N) :: vect,outVect,outVect2, anotherVect
为我消除了段错误。