Распределяемые массивы в структурах данных устройства CUDA-Fortran

Я пытаюсь использовать выделяемые массивы внутри структур данных «устройства», которые находятся в памяти графического процессора. Код (вставленный ниже) компилируется, но выдает segfault. Я делаю что-то явно не так?

Файл модуля называется «gpu_modules.F90», как указано ниже:

!=============
! This module contains definitions for data structures and the data
! stored on the device
!=============

   module GPU_variables
   use cudafor

   type :: data_str_def

!=============
! single number quantities
!=============

      integer                       :: i, j 
      real(kind=8)                  :: a 

!=============
! Arrays
!=============

      real(kind=8),   allocatable   :: b(:)
      real(kind=8),   allocatable   :: c(:,:)
      real(kind=8),   allocatable   :: d(:,:,:)
      real(kind=8),   allocatable   :: e(:,:,:,:)

   end type data_str_def

!=============
! Actual data is here
!=============

   type(data_str_def), device, allocatable   :: data_str(:)

   contains

!=============
! subroutine to allocate memory
!=============

      subroutine allocate_mem(n1)
      implicit none 
      integer, intent(in)  :: n1 

      call deallocate_mem()

      write(*,*) 'works here'
      allocate(data_str(n1))

      write(*,*) 'what about allocating memory?'
      allocate(data_str(n1) % b(10))
      write(*,*) 'success!'

      return
      end subroutine allocate_mem

!=============
! subroutine to deallocate memory
!=============

      subroutine deallocate_mem()
      implicit none
      if(allocated(data_str)) deallocate(data_str)
      return 
      end subroutine deallocate_mem

   end module GPU_variables

Основная программа — «gpu_test.F90», приведенная ниже:

!=============
! main program 
!=============

    program gpu_test
    use gpu_variables
    implicit none

!=============
! local variables
!=============

    integer             :: i, j, n

!=============
! allocate data
!=============

    n       = 2                 ! number of data structures

    call allocate_mem(n)

!=============
! dallocate device data structures and exit
!=============

    call deallocate_mem()
    end program

Команда компиляции (из текущей папки):

pgfortran -Mcuda=cc5x *.F90 

Выход терминала:

$ ./a.out 
 works here
 what about allocating memory?
Segmentation fault (core dumped)

Любая помощь/понимание и решение будут оценены.. и нет, использование указателей не является жизнеспособным вариантом.

Изменить: еще одна деталь, которая может иметь значение: я использую pgfortran версии 16.10.


person ansri    schedule 21.07.2017    source источник
comment
Обратите внимание, что использование kind=8 уродливо и не переносимо (хотя и не вызывает эту ошибку). Кроме того, возвращение перед каждым концом совершенно поверхностно.   -  person Vladimir F    schedule 21.07.2017
comment
Также обратите внимание, что allocate(data_str(n1) % b(10)) выделяет компонент b только для n1 компонента data_str. Но это может быть вашим намерением в этом простом примере.   -  person Vladimir F    schedule 21.07.2017
comment
Возможный дубликат stackoverflow.com/questions/44680150/   -  person Vladimir F    schedule 21.07.2017
comment
привет Владимир: спасибо за ответы. kind=8 был только для того, чтобы все было ясно. Да, я хотел выделить только один компонент производного типа, не трогая остальные. Сначала я также посмотрел на вопрос об указателе в структуре данных - предложенное решение состояло в том, чтобы сделать копию структуры данных на стороне хоста и скопировать все это на устройство ... Я попробую и опубликую ответ   -  person ansri    schedule 22.07.2017
comment
только что попробовал .. не получилось сделать копию хоста и перенести на устройство.   -  person ansri    schedule 22.07.2017
comment
поэтому, согласно документации (руководство PGI openacc, v2015 и v2017): Массивы производного типа, где производный тип содержит выделяемые элементы, не тестировались и не должны считаться поддерживаемыми в этом выпуске. Эта важная функция будет включена в предстоящий выпуск ==> не знаю, относится ли она к самой функции openacc или к компилятору в целом. В любом случае, это кажется нестабильной функцией. Я думаю, мне придется вручную создать его с помощью указателей   -  person ansri    schedule 22.07.2017
comment
Я думаю, вы неправильно поняли цитату. OpenACC здесь роли не играет.   -  person Vladimir F    schedule 22.07.2017
comment
Вы должны показать нам, что вы пробовали и какую ошибку вы получили. Пожалуйста, прочитайте полное обсуждение в stackoverflow.com/questions/44680150/. Я разместил там несколько важных комментариев под своими когтями. Пожалуйста, покажите ваш новый код.   -  person Vladimir F    schedule 22.07.2017
comment
Я также уверен, что вы можете сделать свой пример кода намного короче. Здесь достаточно нескольких строк.   -  person Vladimir F    schedule 22.07.2017


Ответы (2)


Причина ошибки сегментации заключается в том, что вам необходимо получить доступ к памяти для data_str на хосте, чтобы выделить data_str(n1)%b. Поскольку data_str находится в памяти устройства, а не в памяти хоста, вы получаете ошибку сегментации. Теоретически компилятор может создать временный хост, выделить его, а затем скопировать в дескриптор для data_str(n1)%b, но это не является частью сегодняшнего CUDA Fortran.

Вы можете обойти этот случай, создав временный файл самостоятельно:

      subroutine allocate_mem(n1)
      implicit none
      integer, intent(in)  :: n1
      type(data_str_def) :: data_str_h

      call deallocate_mem()

      write(*,*) 'works here'
      allocate(data_str(n1))

      write(*,*) 'what about allocating memory?'
      allocate(data_str_h% b(10))
      data_str(n1) = data_str_h
      write(*,*) 'success!'

      return
      end subroutine allocate_mem

Кстати, вы намерены, чтобы компоненты b, c, d и e размещались в памяти хоста или памяти устройства? Я не вижу на них атрибута устройства, поэтому в приведенном выше примере они переходят в память хоста.

person Rafik Zurob    schedule 24.07.2017
comment
привет Рафик, спасибо за предложение. Структура данных в модуле data_str имеет атрибут устройства, поэтому находится в памяти графического процессора. Любые записи в data_str также наследуют этот атрибут. - person ansri; 30.07.2017
comment
@ansri Все записи в data_str также наследуют этот атрибут. Это неправда! См. ссылку, которую я уже показывал вам stackoverflow.com/questions/44680150/ - person Vladimir F; 31.07.2017