大于90个元素的数组发生分段错误(Fortran绑定,cuBLAS)

时间:2014-03-28 15:37:22

标签: arrays cuda fortran intel-fortran cublas

我正在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

再次感谢!

1 个答案:

答案 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

为我消除了段错误。