Неопределенные ссылки на функции cubas с использованием ifort (привязки cuBLAS Fortran)

У меня есть образец процедуры привязки cuBLAS Fortran, предоставленный из предыдущего вопроса to-fortran">здесь. Я использую Ubuntu 13.10, IFORT 14.0.1 и Cuda 5.5. Код ниже:

cublas.f

      program cublas_fortran_example
      implicit none
      integer i, j

c     helper functions
      integer cublas_init
      integer cublas_shutdown
      integer cublas_alloc
      integer cublas_free
      integer cublas_set_vector
      integer cublas_get_vector
c     selected blas functions
      double precision cublas_ddot
      external cublas_daxpy
      external cublas_dscal
      external cublas_dcopy
      double precision cublas_dnrm2
c     cublas variables
      integer cublas_status
      real*8 x(30), y(30)
      double precision alpha, beta
      double precision nrm
      integer*8 d_x, d_y, d_alpha, d_beta, d_nrm
      integer*8 dsize1, dlength1, dlength2
      double precision dresult



      write(*,*) "testing cublas fortran example"

c     initialize cublas library
c     CUBLAS_STATUS_SUCCESS=0
      cublas_status = cublas_init()
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS Library initialization failed"
         write(*,*) "cublas_status=",cublas_status
         stop
      endif
c     initialize data
      do j=1,30
        x(j) = 1.0
        y(j) = 2.0
      enddo
      dsize1 = 8
      dlength1 = 30
      dlength2 = 1
      alpha = 2.0
      beta = 3.0
c     allocate device storage
      cublas_status = cublas_alloc(dlength1, dsize1, d_x)
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS device malloc failed"
         stop
      endif
      cublas_status = cublas_alloc(dlength1, dsize1, d_y)
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS device malloc failed"
         stop
      endif
      cublas_status = cublas_alloc(dlength2, dsize1, d_alpha)
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS device malloc failed"
         stop
      endif
      cublas_status = cublas_alloc(dlength2, dsize1, d_beta)
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS device malloc failed"
         stop
      endif
      cublas_status = cublas_alloc(dlength2, dsize1, d_nrm)
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS device malloc failed"
         stop
      endif

c     copy data from host to device

      cublas_status = cublas_set_vector(dlength1, dsize1, x, dlength2,
     >     d_x, dlength2)
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS copy to device failed"
         write(*,*) "cublas_status=",cublas_status
         stop
      endif
      cublas_status = cublas_set_vector(dlength1, dsize1, y, dlength2,
     >     d_y, dlength2)
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS copy to device failed"
         write(*,*) "cublas_status=",cublas_status
         stop
      endif

      dresult = cublas_ddot(dlength1, d_x, dlength2, d_y, dlength2)
      write(*,*) "dot product result=",dresult

      dresult = cublas_dnrm2(dlength1, d_x, dlength2)
      write(*,*) "nrm2 of x result=",dresult

      dresult = cublas_dnrm2(dlength1, d_y, dlength2)
      write(*,*) "nrm2 of y result=",dresult

      call cublas_daxpy(dlength1, alpha, d_x, dlength2, d_y, dlength2)
      cublas_status = cublas_get_vector(dlength1, dsize1, d_y, dlength2,
     >     y, dlength2)
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS copy to host failed"
         write(*,*) "cublas_status=",cublas_status
         stop
      endif
      write(*,*) "daxpy y(1)  =", y(1)
      write(*,*) "daxpy y(30) =", y(30)


      call cublas_dscal(dlength1, beta, d_x, dlength2)
      cublas_status = cublas_get_vector(dlength1, dsize1, d_x, dlength2,
     >     x, dlength2)
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS copy to host failed"
         write(*,*) "cublas_status=",cublas_status
         stop
      endif
      write(*,*) "dscal x(1)  =", x(1)
      write(*,*) "dscal x(30) =", x(30)


      call cublas_dcopy(dlength1, d_x, dlength2, d_y, dlength2)
      cublas_status = cublas_get_vector(dlength1, dsize1, d_y, dlength2,
     >     y, dlength2)
      if (cublas_status /= 0) then
         write(*,*) "CUBLAS copy to host failed"
         write(*,*) "cublas_status=",cublas_status
         stop
      endif
      write(*,*) "dcopy y(1)  =", y(1)
      write(*,*) "dcopy y(30) =", y(30)

c     deallocate GPU memory and exit
      cublas_status = cublas_free(d_x)
      cublas_status = cublas_free(d_y)
      cublas_status = cublas_free(d_alpha)
      cublas_status = cublas_free(d_beta)
      cublas_status = cublas_free(d_nrm)
      cublas_status = cublas_shutdown()
      stop
      end

Когда я компилирую с помощью gfortran, я получаю правильный вывод, как показано ниже:

скомпилировать и запустить

$gfortran -c -o cublasf.o cublasf.f
$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
$ ./cublasf 
 testing cublas fortran example
 dot product result=   60.000000000000000     
 nrm2 of x result=   5.4772255750516612     
 nrm2 of y result=   10.954451150103322     
 daxpy y(1)  =   4.0000000000000000     
 daxpy y(30) =   4.0000000000000000     
 dscal x(1)  =   3.0000000000000000     
 dscal x(30) =   3.0000000000000000     
 dcopy y(1)  =   3.0000000000000000     
 dcopy y(30) =   3.0000000000000000     

Однако мне нужно использовать компилятор Intel Fortran с библиотекой cuBLAS, но когда я переключаюсь с gfortran на ifort, я получаю множество неопределенных ссылок, как показано ниже:

$ifort -c -o cublasf.o cublasf.f
$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 -o cublasf cublasf.o fortran.o -L/usr/local/cuda/lib64 -lcublas
cublasf.o: In function `MAIN__':
cublasf.f:(.text+0x8a): undefined reference to `cublas_init_'
cublasf.f:(.text+0x1f5): undefined reference to `cublas_alloc_'
cublasf.f:(.text+0x21c): undefined reference to `cublas_alloc_'
cublasf.f:(.text+0x243): undefined reference to `cublas_alloc_'
cublasf.f:(.text+0x26a): undefined reference to `cublas_alloc_'
cublasf.f:(.text+0x291): undefined reference to `cublas_alloc_'
cublasf.f:(.text+0x2c8): undefined reference to `cublas_set_vector_'
cublasf.f:(.text+0x3d1): undefined reference to `cublas_set_vector_'
cublasf.f:(.text+0x4d5): undefined reference to `cublas_ddot_'
cublasf.f:(.text+0x56f): undefined reference to `cublas_dnrm2_'
cublasf.f:(.text+0x609): undefined reference to `cublas_dnrm2_'
cublasf.f:(.text+0x6b6): undefined reference to `cublas_daxpy_'
cublasf.f:(.text+0x6e6): undefined reference to `cublas_get_vector_'
cublasf.f:(.text+0x8c5): undefined reference to `cublas_dscal_'
cublasf.f:(.text+0x8f5): undefined reference to `cublas_get_vector_'
cublasf.f:(.text+0xad7): undefined reference to `cublas_dcopy_'
cublasf.f:(.text+0xb07): undefined reference to `cublas_get_vector_'
cublasf.f:(.text+0xcce): undefined reference to `cublas_free_'
cublasf.f:(.text+0xcdd): undefined reference to `cublas_free_'
cublasf.f:(.text+0xcec): undefined reference to `cublas_free_'
cublasf.f:(.text+0xcfb): undefined reference to `cublas_free_'
cublasf.f:(.text+0xd0a): undefined reference to `cublas_free_'
cublasf.f:(.text+0xd11): undefined reference to `cublas_shutdown_'

Я видел несколько других сообщений по этой же проблеме, но без реального решения/объяснения. Если бы кто-нибудь мог объяснить, почему эти ссылки не определены при использовании ifort, а не при использовании gfortran, а также какие-либо решения по устранению проблемы, я был бы очень признателен. Огромное спасибо заранее!


person Dylan    schedule 25.03.2014    source источник
comment
Важным моментом, на который следует обратить внимание, является добавление _ в конце символов в испускаемом коде ifort. Вероятно, есть способ контролировать искажение символов в ifort. Я не знаю навскидку, что это такое. В противном случае вам может понадобиться использовать механизм ISO_C_BINDING.   -  person talonmies    schedule 25.03.2014
comment
По умолчанию в Linux ifort используется одиночное подчеркивание (-assume underscore — пожалуйста, прочитайте справочную страницу для получения подробной информации. Как насчет того, чтобы сначала поставить библиотеки? Как в ifort -o cublasf -L/usr/local/cuda/lib64 -lcublas cublasf.o fortran.o .   -  person Timothy Brown    schedule 25.03.2014


Ответы (1)


В в документации Intel Fortran указано, что

В системах Linux и OS X компилятор добавляет символ подчеркивания к внешним определяемым пользователем именам.

Вам нужно отключить его,

ifort -assume nounderscore ...

Также рассмотрите случай names.

Это значение по умолчанию в системах Linux* и OS X*. Компилятор игнорирует различия в регистре идентификаторов и преобразует внешние имена в нижний регистр.

Так что вам, возможно, также понадобится

-names uppercase
person Peter    schedule 26.03.2014
comment
Я попытался использовать ifort -assme nounderscore ... и получил ту же ошибку, что и выше, но без подчеркивания в конце вызова функции. Если это поможет, я пытаюсь получить доступ к оболочкам функций в /usr/local/cuda/src/fortran_common.h. Кажется, он содержит обертки функций, которые мне нужны, под тегом #elif defined(CUBLAS_INTEL_FORTRAN), однако, похоже, он получает доступ к оболочкам под #if defined(CUBLAS_GFORTRAN) || defined(CUBLAS_G95) по выходным данным, которые я получаю. Спасибо - person Dylan; 26.03.2014
comment
что вам дает nm -D /usr/local/cuda/lib64/libcublas.so | grep кублас_инит ? - person Peter; 26.03.2014
comment
Я ничего не получил, когда я запустил его - person Dylan; 26.03.2014
comment
cubas_init определен в /usr/local/cuda/src/fortran.c? - person Peter; 26.03.2014
comment
Да, это. int CUBLAS_INIT (void) { return (int)cublasInit (); } - person Dylan; 26.03.2014
comment
Когда я запускаю nm -D /usr/local/cuda/lib64/libcublas.so | grep "cublasInit". я получаю 000000000001e590 T cublasInit - person Dylan; 26.03.2014
comment
нм fortran.o | grep -i кублас_инит? - person Peter; 26.03.2014
comment
вывод, который я получаю, 0000000000000000 T CUBLAS_INIT - person Dylan; 26.03.2014
comment
когда вы переключаете порядок на ifort ... fortran.o cublasf.o ... ? - person Peter; 26.03.2014
comment
Все еще получаю ту же ошибку, что и выше (кстати, спасибо за время, которое вы потратили, чтобы помочь мне с этим, я очень ценю это) - person Dylan; 26.03.2014
comment
Спасибо!! Добавление «-names uppercase» решило мою проблему. - person Dylan; 26.03.2014
comment
нп; Может быть, вы можете удалить некоторый код из cublas.f, представленного здесь, чтобы было легче читать вопрос в будущем (может быть, просто удалите все после строки cublas_status = cublas_init() и некоторые инициализации до) - person Peter; 26.03.2014