LCOV - code coverage report
Current view: top level - src/offload - offload_api.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:9843133) Lines: 38 58 65.5 %
Date: 2024-05-10 06:53:45 Functions: 7 13 53.8 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: BSD-3-Clause                                                          !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Fortran API for the offload package, which is written in C.
      10             : !> \author Ole Schuett
      11             : ! **************************************************************************************************
      12             : MODULE offload_api
      13             :    USE ISO_C_BINDING,                   ONLY: C_ASSOCIATED,&
      14             :                                               C_CHAR,&
      15             :                                               C_F_POINTER,&
      16             :                                               C_INT,&
      17             :                                               C_NULL_CHAR,&
      18             :                                               C_NULL_PTR,&
      19             :                                               C_PTR,&
      20             :                                               C_SIZE_T
      21             :    USE kinds,                           ONLY: dp,&
      22             :                                               int_8
      23             : #include "../base/base_uses.f90"
      24             : 
      25             :    IMPLICIT NONE
      26             : 
      27             :    PRIVATE
      28             : 
      29             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'offload_api'
      30             : 
      31             :    PUBLIC :: offload_init
      32             :    PUBLIC :: offload_get_device_count
      33             :    PUBLIC :: offload_set_chosen_device, offload_get_chosen_device, offload_activate_chosen_device
      34             :    PUBLIC :: offload_timeset, offload_timestop, offload_mem_info
      35             :    PUBLIC :: offload_buffer_type, offload_create_buffer, offload_free_buffer
      36             :    PUBLIC :: offload_malloc_pinned_mem, offload_free_pinned_mem
      37             : 
      38             :    TYPE offload_buffer_type
      39             :       REAL(KIND=dp), DIMENSION(:), CONTIGUOUS, POINTER :: host_buffer => Null()
      40             :       TYPE(C_PTR)                          :: c_ptr = C_NULL_PTR
      41             :    END TYPE offload_buffer_type
      42             : 
      43             : CONTAINS
      44             : 
      45             : ! **************************************************************************************************
      46             : !> \brief allocate pinned memory.
      47             : !> \param buffer address of the buffer
      48             : !> \param length length of the buffer
      49             : !> \return 0
      50             : ! **************************************************************************************************
      51           0 :    FUNCTION offload_malloc_pinned_mem(buffer, length) RESULT(res)
      52             :       TYPE(C_PTR)                                        :: buffer
      53             :       INTEGER(C_SIZE_T), VALUE                           :: length
      54             :       INTEGER                                            :: res
      55             : 
      56             :       INTERFACE
      57             :          FUNCTION offload_malloc_pinned_mem_c(buffer, length) &
      58             :             BIND(C, name="offload_host_malloc")
      59             :             IMPORT C_SIZE_T, C_PTR, C_INT
      60             :             TYPE(C_PTR)              :: buffer
      61             :             INTEGER(C_SIZE_T), VALUE :: length
      62             :             INTEGER(KIND=C_INT)                :: offload_malloc_pinned_mem_c
      63             :          END FUNCTION offload_malloc_pinned_mem_c
      64             :       END INTERFACE
      65             : 
      66           0 :       res = offload_malloc_pinned_mem_c(buffer, length)
      67           0 :    END FUNCTION offload_malloc_pinned_mem
      68             : 
      69             : ! **************************************************************************************************
      70             : !> \brief free pinned memory
      71             : !> \param buffer address of the buffer
      72             : !> \return 0
      73             : ! **************************************************************************************************
      74           0 :    FUNCTION offload_free_pinned_mem(buffer) RESULT(res)
      75             :       TYPE(C_PTR), VALUE                                 :: buffer
      76             :       INTEGER                                            :: res
      77             : 
      78             :       INTERFACE
      79             :          FUNCTION offload_free_pinned_mem_c(buffer) &
      80             :             BIND(C, name="offload_host_free")
      81             :             IMPORT C_PTR, C_INT
      82             :             INTEGER(KIND=C_INT)                :: offload_free_pinned_mem_c
      83             :             TYPE(C_PTR), VALUE            :: buffer
      84             :          END FUNCTION offload_free_pinned_mem_c
      85             :       END INTERFACE
      86             : 
      87           0 :       res = offload_free_pinned_mem_c(buffer)
      88           0 :    END FUNCTION offload_free_pinned_mem
      89             : 
      90             : ! **************************************************************************************************
      91             : !> \brief Initialize runtime.
      92             : !> \return ...
      93             : !> \author Rocco Meli
      94             : ! **************************************************************************************************
      95        8388 :    SUBROUTINE offload_init()
      96             :       INTERFACE
      97             :          SUBROUTINE offload_init_c() &
      98             :             BIND(C, name="offload_init")
      99             :          END SUBROUTINE offload_init_c
     100             :       END INTERFACE
     101             : 
     102        8388 :       CALL offload_init_c()
     103             : 
     104        8388 :    END SUBROUTINE offload_init
     105             : 
     106             : ! **************************************************************************************************
     107             : !> \brief Returns the number of available devices.
     108             : !> \return ...
     109             : !> \author Ole Schuett
     110             : ! **************************************************************************************************
     111        8392 :    FUNCTION offload_get_device_count() RESULT(count)
     112             :       INTEGER                                            :: count
     113             : 
     114             :       INTERFACE
     115             :          FUNCTION offload_get_device_count_c() &
     116             :             BIND(C, name="offload_get_device_count")
     117             :             IMPORT :: C_INT
     118             :             INTEGER(KIND=C_INT)                :: offload_get_device_count_c
     119             :          END FUNCTION offload_get_device_count_c
     120             :       END INTERFACE
     121             : 
     122        8392 :       count = offload_get_device_count_c()
     123             : 
     124        8392 :    END FUNCTION offload_get_device_count
     125             : 
     126             : ! **************************************************************************************************
     127             : !> \brief Selects the chosen device to be used.
     128             : !> \param device_id ...
     129             : !> \author Ole Schuett
     130             : ! **************************************************************************************************
     131           0 :    SUBROUTINE offload_set_chosen_device(device_id)
     132             :       INTEGER, INTENT(IN)                                :: device_id
     133             : 
     134             :       INTERFACE
     135             :          SUBROUTINE offload_set_chosen_device_c(device_id) &
     136             :             BIND(C, name="offload_set_chosen_device")
     137             :             IMPORT :: C_INT
     138             :             INTEGER(KIND=C_INT), VALUE                :: device_id
     139             :          END SUBROUTINE offload_set_chosen_device_c
     140             :       END INTERFACE
     141             : 
     142           0 :       CALL offload_set_chosen_device_c(device_id=device_id)
     143             : 
     144           0 :    END SUBROUTINE offload_set_chosen_device
     145             : 
     146             : ! **************************************************************************************************
     147             : !> \brief Returns the chosen device.
     148             : !> \return ...
     149             : !> \author Ole Schuett
     150             : ! **************************************************************************************************
     151           0 :    FUNCTION offload_get_chosen_device() RESULT(device_id)
     152             :       INTEGER                                            :: device_id
     153             : 
     154             :       INTERFACE
     155             :          FUNCTION offload_get_chosen_device_c() &
     156             :             BIND(C, name="offload_get_chosen_device")
     157             :             IMPORT :: C_INT
     158             :             INTEGER(KIND=C_INT)                :: offload_get_chosen_device_c
     159             :          END FUNCTION offload_get_chosen_device_c
     160             :       END INTERFACE
     161             : 
     162           0 :       device_id = offload_get_chosen_device_c()
     163             : 
     164           0 :       IF (device_id < 0) &
     165           0 :          CPABORT("No offload device has been chosen.")
     166             : 
     167           0 :    END FUNCTION offload_get_chosen_device
     168             : 
     169             : ! **************************************************************************************************
     170             : !> \brief Activates the device selected via offload_set_chosen_device()
     171             : !> \author Ole Schuett
     172             : ! **************************************************************************************************
     173     1320378 :    SUBROUTINE offload_activate_chosen_device()
     174             : 
     175             :       INTERFACE
     176             :          SUBROUTINE offload_activate_chosen_device_c() &
     177             :             BIND(C, name="offload_activate_chosen_device")
     178             :          END SUBROUTINE offload_activate_chosen_device_c
     179             :       END INTERFACE
     180             : 
     181     1320378 :       CALL offload_activate_chosen_device_c()
     182             : 
     183     1320378 :    END SUBROUTINE offload_activate_chosen_device
     184             : 
     185             : ! **************************************************************************************************
     186             : !> \brief Starts a timing range.
     187             : !> \param routineN ...
     188             : !> \author Ole Schuett
     189             : ! **************************************************************************************************
     190  1535541262 :    SUBROUTINE offload_timeset(routineN)
     191             :       CHARACTER(LEN=*), INTENT(IN)                       :: routineN
     192             : 
     193             :       INTERFACE
     194             :          SUBROUTINE offload_timeset_c(message) BIND(C, name="offload_timeset")
     195             :             IMPORT :: C_CHAR
     196             :             CHARACTER(kind=C_CHAR), DIMENSION(*), INTENT(IN) :: message
     197             :          END SUBROUTINE offload_timeset_c
     198             :       END INTERFACE
     199             : 
     200  1535541262 :       CALL offload_timeset_c(TRIM(routineN)//C_NULL_CHAR)
     201             : 
     202  1535541262 :    END SUBROUTINE offload_timeset
     203             : 
     204             : ! **************************************************************************************************
     205             : !> \brief  Ends a timing range.
     206             : !> \author Ole Schuett
     207             : ! **************************************************************************************************
     208  1535541262 :    SUBROUTINE offload_timestop()
     209             : 
     210             :       INTERFACE
     211             :          SUBROUTINE offload_timestop_c() BIND(C, name="offload_timestop")
     212             :          END SUBROUTINE offload_timestop_c
     213             :       END INTERFACE
     214             : 
     215  1535541262 :       CALL offload_timestop_c()
     216             : 
     217  1535541262 :    END SUBROUTINE offload_timestop
     218             : 
     219             : ! **************************************************************************************************
     220             : !> \brief Gets free and total device memory.
     221             : !> \param free ...
     222             : !> \param total ...
     223             : !> \author Ole Schuett
     224             : ! **************************************************************************************************
     225           0 :    SUBROUTINE offload_mem_info(free, total)
     226             :       INTEGER(KIND=int_8), INTENT(OUT)                   :: free, total
     227             : 
     228             :       INTEGER(KIND=C_SIZE_T)                             :: my_free, my_total
     229             :       INTERFACE
     230             :          SUBROUTINE offload_mem_info_c(free, total) BIND(C, name="offload_mem_info")
     231             :             IMPORT :: C_SIZE_T
     232             :             INTEGER(KIND=C_SIZE_T)                   :: free, total
     233             :          END SUBROUTINE offload_mem_info_c
     234             :       END INTERFACE
     235             : 
     236           0 :       CALL offload_mem_info_c(my_free, my_total)
     237             : 
     238             :       ! On 32-bit architectures this converts from int_4 to int_8.
     239           0 :       free = my_free
     240           0 :       total = my_total
     241             : 
     242           0 :    END SUBROUTINE offload_mem_info
     243             : 
     244             : ! **************************************************************************************************
     245             : !> \brief Allocates a buffer of given length, ie. number of elements.
     246             : !> \param length ...
     247             : !> \param buffer ...
     248             : !> \author Ole Schuett
     249             : ! **************************************************************************************************
     250      249706 :    SUBROUTINE offload_create_buffer(length, buffer)
     251             :       INTEGER, INTENT(IN)                                :: length
     252             :       TYPE(offload_buffer_type), INTENT(INOUT)           :: buffer
     253             : 
     254             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'offload_create_buffer'
     255             : 
     256             :       INTEGER                                            :: handle
     257             :       TYPE(C_PTR)                                        :: host_buffer_c
     258             :       INTERFACE
     259             :          SUBROUTINE offload_create_buffer_c(length, buffer) &
     260             :             BIND(C, name="offload_create_buffer")
     261             :             IMPORT :: C_PTR, C_INT
     262             :             INTEGER(KIND=C_INT), VALUE                :: length
     263             :             TYPE(C_PTR)                               :: buffer
     264             :          END SUBROUTINE offload_create_buffer_c
     265             :       END INTERFACE
     266             :       INTERFACE
     267             : 
     268             :          FUNCTION offload_get_buffer_host_pointer_c(buffer) &
     269             :             BIND(C, name="offload_get_buffer_host_pointer")
     270             :             IMPORT :: C_PTR
     271             :             TYPE(C_PTR), VALUE                        :: buffer
     272             :             TYPE(C_PTR)                               :: offload_get_buffer_host_pointer_c
     273             :          END FUNCTION offload_get_buffer_host_pointer_c
     274             :       END INTERFACE
     275             : 
     276      249706 :       CALL timeset(routineN, handle)
     277             : 
     278      249706 :       IF (ASSOCIATED(buffer%host_buffer)) THEN
     279       10692 :          IF (SIZE(buffer%host_buffer) == 0) DEALLOCATE (buffer%host_buffer)
     280             :       END IF
     281             : 
     282      249706 :       CALL offload_create_buffer_c(length=length, buffer=buffer%c_ptr)
     283      249706 :       CPASSERT(C_ASSOCIATED(buffer%c_ptr))
     284             : 
     285      249706 :       IF (length == 0) THEN
     286             :          ! While C_F_POINTER usually accepts a NULL pointer it's not standard compliant.
     287         452 :          ALLOCATE (buffer%host_buffer(0))
     288             :       ELSE
     289      249254 :          host_buffer_c = offload_get_buffer_host_pointer_c(buffer%c_ptr)
     290      249254 :          CPASSERT(C_ASSOCIATED(host_buffer_c))
     291      498508 :          CALL C_F_POINTER(host_buffer_c, buffer%host_buffer, shape=(/length/))
     292             :       END IF
     293             : 
     294      249706 :       CALL timestop(handle)
     295      249706 :    END SUBROUTINE offload_create_buffer
     296             : 
     297             : ! **************************************************************************************************
     298             : !> \brief Deallocates given buffer.
     299             : !> \param buffer ...
     300             : !> \author Ole Schuett
     301             : ! **************************************************************************************************
     302      240766 :    SUBROUTINE offload_free_buffer(buffer)
     303             :       TYPE(offload_buffer_type), INTENT(INOUT)           :: buffer
     304             : 
     305             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'offload_free_buffer'
     306             : 
     307             :       INTEGER                                            :: handle
     308             :       INTERFACE
     309             :          SUBROUTINE offload_free_buffer_c(buffer) &
     310             :             BIND(C, name="offload_free_buffer")
     311             :             IMPORT :: C_PTR
     312             :             TYPE(C_PTR), VALUE                        :: buffer
     313             :          END SUBROUTINE offload_free_buffer_c
     314             :       END INTERFACE
     315             : 
     316      240766 :       CALL timeset(routineN, handle)
     317             : 
     318      240766 :       IF (C_ASSOCIATED(buffer%c_ptr)) THEN
     319             : 
     320      239014 :          CALL offload_free_buffer_c(buffer%c_ptr)
     321             : 
     322      239014 :          buffer%c_ptr = C_NULL_PTR
     323             : 
     324      239014 :          IF (SIZE(buffer%host_buffer) == 0) THEN
     325         346 :             DEALLOCATE (buffer%host_buffer)
     326             :          ELSE
     327      238668 :             NULLIFY (buffer%host_buffer)
     328             :          END IF
     329             :       END IF
     330             : 
     331      240766 :       CALL timestop(handle)
     332      240766 :    END SUBROUTINE offload_free_buffer
     333           0 : END MODULE offload_api

Generated by: LCOV version 1.15